def __init__(self, context):
        super(KillPlugin, self).__init__(context)
        self.setObjectName('KillPlugin')

        self._listener = KillListener()
        self._broadcaster = KillBroadcaster(rospy.get_name(),
                                            'Software kill using KillPlugin')
        self._kill_active = False

        self._widget = QWidget()
        loadUi(os.path.join(uipath, 'killplugin.ui'), self._widget)
        context.add_widget(self._widget)

        self._widget.findChild(QTableWidget,
                               'killTable').setHorizontalHeaderLabels(
                                   ["Name", "Status", "Description"])

        self._widget.findChild(QPushButton, 'killButton').clicked.connect(
            self._on_kill_clicked)
        self._widget.findChild(QPushButton, 'unkillButton').clicked.connect(
            self._on_unkill_clicked)
        self._widget.findChild(QPushButton, 'runButton').clicked.connect(
            self._on_run_clicked)

        self._update_timer = QTimer(self._widget)
        self._update_timer.timeout.connect(self._on_update)
        self._update_timer.start(100)
Пример #2
0
	def __init__(self):
		rospy.init_node('tank_steer_pd', anonymous=False)

	# Grab params
		if rospy.has_param('~simulate'):
			self.simulate = rospy.get_param('~simulate')
		else:
			self.simulate = 0


		self.max_thrust = rospy.get_param('/max_thrust', 100.0)
		self.min_thrust = rospy.get_param('/min_thrust', -100.0)

		self.L = rospy.get_param('distance_between_thrusters', 0.6096) #meters

	# Set up publishers for servo position and prop speed
		self.thrust_pub = rospy.Publisher('thruster_config', thrusterNewtons, queue_size = 10)
		self.servo_pub = rospy.Publisher('dynamixel/dynamixel_full_config', DynamixelFullConfig, queue_size = 10)

	# Initilize kill
		self.killed = False
		self.kill_listener = KillListener(self.set_kill, self.clear_kill)
		self.kill_broadcaster = KillBroadcaster(id=rospy.get_name(), description='Tank steer PD shutdown')
		rospy.on_shutdown(self.on_shutdown)
		# Clear in case it was previously killed
		try:
			self.kill_broadcaster.clear()
		except rospy.service.ServiceException, e:
			rospy.logwarn(str(e))
Пример #3
0
class send_action:

    def __init__(self, name):
        self.action = actionlib.SimpleActionServer('moveto', MoveToAction, self.new_goal, False)
        self.trajectory_pub = rospy.Publisher('/trajectory', PoseTwistStamped, queue_size=10)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)

        self.action.start()
        self.to_pose = PoseTwistStamped()
        self.temp_pose = PoseTwistStamped()
        self.killed = False
        self.waypoint = False

    def callback(self, msg):
        self.waypoint = msg.data


    def set_kill(self):

        self.to_pose = PoseTwistStamped()

        # TODO --> Verify that all values are at 0

        #members = [attr for attr in dir(self.to_pose.posetwist.pose) if attr.startswith("position") or attr.startswith("orientation")]
        #getattr(self.to_pose.posetwist.pose.position, "x") == 0
        rospy.logwarn('Azi_Drive waypoint kill flag off -- All trajectories at 0: %s' % self.kill_listener.get_kills())
        self.killed = True
        
    def clear_kill(self):
        self.killed = False
        rospy.logwarn('Azi_Drive waypoint kill flag off -- Waypoints enabled: %s' % self.kill_listener.get_kills())

    def new_goal(self, goal):
        self.waypoint = False
        self.temp_pose = PoseTwistStamped()
        self.temp_pose.posetwist = goal.posetwist
        self.temp_pose.header = goal.header
        time.sleep(5)
        self.waypoint_progress = rospy.Subscriber('/waypoint_progress', Bool, self.callback)
        while self.waypoint == False:
            None

        self.action.set_succeeded()
        self.waypoint = True

        

    def over_and_over(self):
        r = rospy.Rate(1)
        if self.killed == True:
            rospy.logwarn('Azi_Drive waypoint kill flag on  -- Waypoints disabled: %s' % self.kill_listener.get_kills())
        if self.killed == False:
            self.to_pose = self.temp_pose
            self.trajectory_pub.publish(self.to_pose)
            print self.to_pose.posetwist.pose
            self.to_pose = PoseTwistStamped()
        r.sleep()
Пример #4
0
    def __init__(self, name):
        self.action = actionlib.SimpleActionServer('moveto', MoveToAction, self.new_goal, False)
        self.trajectory_pub = rospy.Publisher('/trajectory', PoseTwistStamped, queue_size=10)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)

        self.action.start()
        self.to_pose = PoseTwistStamped()
        self.temp_pose = PoseTwistStamped()
        self.killed = False
        self.waypoint = False
Пример #5
0
 def __init__(self, plan_names, master_timeout=None):
     self._plans = PlanSet(plan_names)
     self._master_timeout = master_timeout
     self._sm = None
     self._shared = uf_smach.util.StateSharedHandles()
     self._pub = rospy.Publisher('mission/plans', PlansStamped)
     self._srv = rospy.Service('mission/modify_plan', ModifyPlan, self._modify_plan)
     self._run_srv = actionlib.SimpleActionServer('mission/run', RunMissionsAction,
                                                  self.execute, False)
     self._run_srv.register_preempt_callback(self._on_preempt)
     self._run_srv.start()
     self._tim = rospy.Timer(rospy.Duration(.1), lambda _: self._publish_plans())
     self._kill_listener = KillListener(self._on_preempt)
Пример #6
0
    def __init__(self, name):
        # Set up publishers
        self.wrench_pub = rospy.Publisher('wrench',
                                          WrenchStamped,
                                          queue_size=10)

        # Initilize kill
        self.killed = False
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)
        self.kill_broadcaster = KillBroadcaster(
            id=name, description='Tank steer wrench_generator shutdown')
        rospy.on_shutdown(self.on_shutdown)
        # Clear in case it was previously killed
        try:
            self.kill_broadcaster.clear()
        except rospy.service.ServiceException, e:
            rospy.logwarn(str(e))
Пример #7
0
    def __init__(self, name):
        # Implement the moveto action server
        self.moveto_as = actionlib.SimpleActionServer('moveto', MoveToAction, None, False)
        # Thread Locking
        self.as_lock = self.moveto_as.action_server.lock
        self.moveto_as.register_goal_callback(self.new_goal)
        self.moveto_as.register_preempt_callback(self.goal_preempt)

        # Trajectory generator (using stratagy design pattern where traj_gen is the stratagy)
        self.traj_gen = None

        # Desired pose
        self.desired_position = self.current_position = np.zeros(3)
        self.desired_orientation = self.current_orientation = np.zeros(3)
        #self.desired_twist = self.current_twist = Twist()

        # Goal tolerances before seting succeded
        self.linear_tolerance = rospy.get_param('linear_tolerance', 1.25)
        self.angular_tolerance = rospy.get_param('angular_tolerance', 20 * np.pi / 180)

        # Publishers
        self.traj_pub = rospy.Publisher('/trajectory', PoseTwistStamped, queue_size = 10)
        self.traj_debug_pub = rospy.Publisher('/trajectory_debug', PoseStamped, queue_size = 10)
        self.goal_debug_pub = rospy.Publisher('/goal_debug', PoseStamped, queue_size = 10)

        # Set desired twist to 0
        #self.desired_twist.linear.x = self.desired_twist.linear.y = self.desired_twist.linear.z = 0
        #self.desired_twist.angular.x = self.desired_twist.angular.y = self.desired_twist.angular.z = 0

        # Wait for current position and set as desired position
        rospy.loginfo('Waiting for /odom')
        self.odom_sub = rospy.Subscriber('/odom', Odometry, self.odom_cb, queue_size = 10)
        while not self.current_position.any(): pass # Will be 0 until an odom publishes (if its still 0 it will drift very very soon)
        self.desired_position = self.current_position
        self.desired_orientation = self.current_orientation
        rospy.loginfo('Got current pose from /odom')

        # Kill handling
        self.killed = False
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)
        self.kill_broadcaster = KillBroadcaster(id=name, description='Azi waypoint shutdown')
        try:
            self.kill_broadcaster.clear()           # In case previously killed
        except rospy.service.ServiceException, e:
            rospy.logwarn(str(e))
Пример #8
0
def start():
	global kill_listener
	global kill_broadcaster

	#Init node
	rospy.init_node('remote_control')

	# Register xbox_rc as a controller
	rospy.wait_for_service('/controller/register_controller', 30.0)
	register_controller_proxy('xbox_rc')

	# Request to switch to xbox_rc
	request_controller_proxy('xbox_rc')

	kill_broadcaster = KillBroadcaster(id=rospy.get_name(), description='Remote control kill')
	kill_listener = KillListener(killed_cb, unkilled_cb)
	try:
		kill_broadcaster.clear()
	except rospy.service.ServiceException, e:
		rospy.logwarn(str(e))
Пример #9
0
    def __init__(self, context):
        super(KillPlugin, self).__init__(context)
        self.setObjectName('KillPlugin')

        self._listener = KillListener()
        self._broadcaster = KillBroadcaster(rospy.get_name(), 'Software kill using KillPlugin')
        self._kill_active = False

        self._widget = QWidget()
        loadUi(os.path.join(uipath, 'killplugin.ui'), self._widget)
        context.add_widget(self._widget)

        self._widget.findChild(QTableWidget, 'killTable').setHorizontalHeaderLabels(["Name", "Status", "Description"])

        self._widget.findChild(QPushButton, 'killButton').clicked.connect(self._on_kill_clicked)
        self._widget.findChild(QPushButton, 'unkillButton').clicked.connect(self._on_unkill_clicked)
        self._widget.findChild(QPushButton, 'runButton').clicked.connect(self._on_run_clicked)

        self._update_timer = QTimer(self._widget)
        self._update_timer.timeout.connect(self._on_update)
        self._update_timer.start(100)
Пример #10
0
def thrusterCtrl():
    global port_current
    global starboard_current
    global kill_listener
    global kill_broadcaster
    global control_kill
    
    #Setup ros
    rospy.init_node('thruster_control')
    #rospy.Subscriber("control_arbiter", Bool, control_callback)
    rospy.Subscriber("thruster_config", thrusterNewtons, motorConfigCallback)
    r = rospy.Rate(UPDATE_RATE)          #1000 hz(1ms Period)... I think
    pub_timer = rospy.Timer(PUB_RATE, pubStatus)

    # Initilize kill
    kill_listener = KillListener(set_kill, clear_kill)
    kill_broadcaster = KillBroadcaster(id=rospy.get_name(), description='Newtons to PWM shutdown')
    # Clear in case it was previously killed
    try:
        kill_broadcaster.clear()
    except rospy.service.ServiceException, e:
        rospy.logwarn(str(e))
Пример #11
0
    def __init__(self, rate=100):
        '''I can't swim on account of my ass-mar'''

        # Register azi_drive as a controller
        rospy.wait_for_service('/controller/register_controller', 30.0)
        rospy.ServiceProxy('/controller/register_controller',
                           register_controller)('azi_drive')

        self.rate = rate
        self.servo_max_rotation = 6.0
        self.controller_max_rotation = self.servo_max_rotation / self.rate

        # rospy.init_node('azi_drive', log_level=rospy.WARN)

        # Set up kill handling
        self.kill_listener = KillListener(self.on_kill, self.on_unkill)
        self.kill_broadcaster = KillBroadcaster(
            id='Azi_drive', description='Azi drive node shutdown')
        try:
            self.kill_broadcaster.clear()
        except rospy.service.ServiceException, e:
            rospy.logwarn(str(e))
Пример #12
0
class MissionServer(object):
    def __init__(self, plan_names, master_timeout=None):
        self._plans = PlanSet(plan_names)
        self._master_timeout = master_timeout
        self._sm = None
        self._shared = uf_smach.util.StateSharedHandles()
        self._pub = rospy.Publisher('mission/plans', PlansStamped)
        self._srv = rospy.Service('mission/modify_plan', ModifyPlan, self._modify_plan)
        self._run_srv = actionlib.SimpleActionServer('mission/run', RunMissionsAction,
                                                     self.execute, False)
        self._run_srv.register_preempt_callback(self._on_preempt)
        self._run_srv.start()
        self._tim = rospy.Timer(rospy.Duration(.1), lambda _: self._publish_plans())
        self._kill_listener = KillListener(self._on_preempt)

    def get_plan(self, plan):
        return self._plans.get_plan(plan)

    def execute(self, goal):
        self._sm = self._plans.make_sm(self._shared, self._master_timeout)
        sis = smach_ros.IntrospectionServer('mission_planner', self._sm, '/SM_ROOT')
        sis.start()
        print 'Waiting for unkill'
        while self._kill_listener.get_killed():
            rospy.sleep(.1)
        outcome = self._sm.execute()
        sis.stop()
        self._shared['moveto'].cancel_goal()
        if outcome == 'succeeded':
            self._run_srv.set_succeeded(RunMissionsResult(outcome))
        else:
            self._run_srv.set_preempted()

    def _on_preempt(self):
        if self._sm is not None:
            self._sm.request_preempt()
    
    def _publish_plans(self):
        self._pub.publish(PlansStamped(
                header=Header(stamp=rospy.Time.now()),
                plans=[Plan(name=name,
                            entries=[uf_smach.msg.PlanEntry(entry.mission, rospy.Duration(entry.timeout),
                                                            entry.contigency_plan, entry.path, entry.dist)
                                     for entry in self._plans.get_plan(name)])
                       for name in self._plans.get_plans()],
                available_missions=get_missions()))

    def _modify_plan(self, req):
        if req.plan not in self._plans.get_plans():
            return None
        plan = self._plans.get_plan(req.plan)
        entry = PlanEntry(req.entry.mission,
                          req.entry.timeout.to_sec(),
                          req.entry.contigency_plan if len(req.entry.contigency_plan) > 0 else None,
                          req.entry.path if req.entry.path != 'none' else None,
                          req.entry.dist)
        if req.operation == ModifyPlanRequest.INSERT:
            if req.pos > len(plan):
                return None
            plan.insert(req.pos, entry)
        elif req.operation == ModifyPlanRequest.REMOVE:
            if req.pos >= len(plan):
                return None
            del plan[req.pos]
        elif req.operation == ModifyPlanRequest.REPLACE:
            if req.pos >= len(plan):
                return None
            plan[req.pos] = entry
        else:
            return None
        return ()
Пример #13
0
class Controller(object):
    def __init__(self):

        # Old gains
        self.d_x = 175
        self.d_y = 90
        self.d_z = 60
        self.p_x = 30
        self.p_y = 30
        self.p_z = 40

        #self.d_x = 175
        #self.d_y = 90
        #self.d_z = 90
        #self.p_x = 40
        #self.p_y = 40
        #self.p_z = 100

        self.killed = False
        self.enable = True
        self.odom_active = False

        self.K_d = numpy.array([
        [self.d_x,0,0,0,0,0],
        [0,self.d_y,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,self.d_z]])

        self.K_p = numpy.array([
        [self.p_x,0,0,0,0,0],
        [0,self.p_y,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,self.p_z]])

        # Averaging parameters
        self.last_average = numpy.zeros(6)
        self.num_to_avg = 75 # At 50 hz this is 50 samples is one second of data
        self.outputs = deque([numpy.zeros(6) for i in range(0, self.num_to_avg)])
        
        self.desired_state_set = False
        self.desired_state = numpy.ones(6)
        self.desired_state_dot = numpy.ones(6)
        self.state = numpy.ones(6)
        self.previous_error = numpy.ones(6)
        self.state_dot = numpy.ones(6)
        self.state_dot_body = numpy.ones(6)

        self.lock = threading.Lock()

        # Get tf listener
        self.tf_listener = tf.TransformListener()

        rospy.Subscriber("pd_d_gain", Point, self.d_gain_callback)
        rospy.Subscriber("pd_p_gain", Point, self.p_gain_callback)
        rospy.Subscriber('/trajectory', PoseTwistStamped, self.desired_state_callback)
        rospy.Subscriber('/odom', Odometry, self.odom_callback)
        self.controller_wrench = rospy.Publisher('wrench', WrenchStamped, queue_size = 1)
        self.waypoint_progress = rospy.Publisher('waypoint_progress', Bool, queue_size = 1)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)

        self.z_error = 0
        self.x_error = 0
        self.y_error = 0

        self.dz_error = 0
        self.dx_error = 0
        self.dy_error = 0

    def set_kill(self):
        self.killed = True
        rospy.logwarn('PD_Controller KILLED: %s' % self.kill_listener.get_kills())

    def clear_kill(self):
        self.killed = False
        rospy.logwarn('PD_Controller ACTIVE: %s' % self.kill_listener.get_kills())

    def d_gain_callback(self, msg):
        self.d_x = msg.x
        self.d_y = msg.y
        self.d_z = msg.z

        self.K_d = numpy.array([
        [self.d_x,0,0,0,0,0],
        [0,self.d_y,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,self.d_z]])

    def p_gain_callback(self, msg):
        self.p_x = msg.x
        self.p_y = msg.y
        self.p_z = msg.z

        self.K_p = numpy.array([
        [self.p_x,0,0,0,0,0],
        [0,self.p_y,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,self.p_z]])

    def desired_state_callback(self,desired_posetwist):
        self.lock.acquire()
        self.desired_state_set = True

        self.desired_state = numpy.concatenate([xyz_array(desired_posetwist.posetwist.pose.position), transformations.euler_from_quaternion(xyzw_array(desired_posetwist.posetwist.pose.orientation))])
        self.desired_state_dot = numpy.concatenate([xyz_array(desired_posetwist.posetwist.twist.linear), xyz_array(desired_posetwist.posetwist.twist.angular)])
        self.lock.release()

    def odom_callback(self, current_posetwist):
        self.lock.acquire()
        self.odom_active = True

        # Grab position; 0 Z
        pose = xyz_array(current_posetwist.pose.pose.position)
        pose[2] = 0

        # Grab orientation; 0 pitch and roll
        orientation = numpy.array(transformations.euler_from_quaternion(xyzw_array(current_posetwist.pose.pose.orientation)))
        orientation[0:2] = 0

        self.state = numpy.concatenate([xyz_array(current_posetwist.pose.pose.position), transformations.euler_from_quaternion(xyzw_array(current_posetwist.pose.pose.orientation))])
        self.state_dot = numpy.concatenate([xyz_array(current_posetwist.twist.twist.linear), xyz_array(current_posetwist.twist.twist.angular)])
        if (not self.desired_state_set):
            self.desired_state = self.state
            self.desired_state_set = True
        self.lock.release()

    def main_loop(self, event):
        
        self.lock.acquire()
        #print 'desired state', desired_state
        #print 'current_state', state
        def smallest_coterminal_angle(x):
            return (x + math.pi) % (2*math.pi) - math.pi

        

        # sub pd-controller sans rise
        rot = None
        # Get tf from /enu to /base_link
        #   Since we are dealing with differences and not absolute positions not translation is required
        try:
            (_, rot) = self.tf_listener.lookupTransform('/base_link', '/enu', rospy.Time(0))
        except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException) as e:
            rospy.logwarn('Tf exception: ' + str(e))

        if rot is not None:
            # Convert to euler angle ( we only care about rotation about z)
            theta = quat_to_rotvec(numpy.array(rot))[2] 

            # Difference in /enu frame
            to_desired_state = self.desired_state[0:2] - self.state[0:2]

            # Convert to base_link
            s = numpy.sin(theta)
            c = numpy.cos(theta)
            rot_matrix_enu_base = numpy.array([[c, -s],
                                               [s, c]])
            to_desired_state = rot_matrix_enu_base.dot(to_desired_state)
            to_desired_state = numpy.insert(to_desired_state, 2, 0) # Append a zero for z


            #                                    Note: Angular differences are the same in base_link as enu so no tf required
            e = numpy.concatenate([to_desired_state, map(smallest_coterminal_angle, self.desired_state[3:6] - self.state[3:6])]) # e_1 in paper

            # Convert desired state dot into base_link
            #   angular velocities do not rquire transformation as they are differences (rendering them frameless)
            #   To convert velocites from enu + desired_orientation to base link:
            #       transform to enu: rotate the velocity vector by desired_orientation
            #       transform to base link: rotate the velocity vector by the angle between enu and base_link
            vels = self.desired_state_dot[0:2]
            theta2 = self.desired_state[5]
            s = numpy.sin(theta2)
            c = numpy.cos(theta2)
            rot_matrix_desired_enu = numpy.array([[c, -s],
                                                  [s, c]])
            vels = rot_matrix_desired_enu.dot(vels)
            vels = rot_matrix_enu_base.dot(vels)

            vels = numpy.insert(vels, 2, 0)

            desired_state_dot = numpy.concatenate([vels, self.desired_state_dot[3:6]])

            #print 'Desired_state tf: ', desired_state_dot
            e_dot = desired_state_dot - self.state_dot
            output = self.K_p.dot(e) + self.K_d.dot(e_dot)

            # Apply simple moving average filter
            new = output / self.num_to_avg
            old = (self.outputs[0] / self.num_to_avg) 
            self.last_average = self.last_average - old + new
            self.outputs.popleft()
            self.outputs.append(output)

            # Resuse output var
            #print 'Outputs: ', self.outputs
            output = self.last_average

            #print 'Last Average: ', output
            self.lock.release()

            self.x_error = e[0]
            self.y_error = e[1]
            self.z_error = e[5]

            self.dx_error = e_dot[0]
            self.dy_error = e_dot[1]
            self.dz_error = e_dot[5]

            #self.to_terminal()            
            
            if (not(self.odom_active)):
                output = [0,0,0,0,0,0]
            if (self.enable & self.killed==False):
                self.controller_wrench.publish(WrenchStamped(
                    header = Header(
                        stamp=rospy.Time.now(),
                        frame_id="/base_link",
                        ),
                    wrench=Wrench(
                        force = Vector3(x= output[0],y= output[1],z= 0),
                        torque = Vector3(x=0,y= 0,z= output[5]),
                        ))
                        
                        )

                if((self.x_error < 1) & (self.y_error < 1) & (self.z_error < 1)):
                        self.waypoint_progress.publish(True)

            if (self.killed == True):
                rospy.logwarn('PD_Controller KILLED: %s' % self.kill_listener.get_kills())
                self.controller_wrench.publish(WrenchStamped(
                        header = Header(
                            stamp=rospy.Time.now(),
                            frame_id="/base_link",
                            ),
                        wrench=Wrench(
                            force = Vector3(x= 0,y= 0,z= 0),
                            torque = Vector3(x=0,y= 0,z= 0),
                            ))
                            
                            )

        else:
            self.lock.release()

    def timeout_callback(self, event):
        self.odom_active = False

    def to_terminal(self):
        print "X: ", self.x_error
        print "Y: ", self.y_error
        print "Z: ", self.z_error

        print "dX: ", self.dx_error
        print "dY: ", self.dy_error
        print "dZ: ", self.dz_error
Пример #14
0
    def __init__(self):

        # Old gains
        self.d_x = 175
        self.d_y = 90
        self.d_z = 60
        self.p_x = 30
        self.p_y = 30
        self.p_z = 40

        #self.d_x = 175
        #self.d_y = 90
        #self.d_z = 90
        #self.p_x = 40
        #self.p_y = 40
        #self.p_z = 100

        self.killed = False
        self.enable = True
        self.odom_active = False

        self.K_d = numpy.array([
        [self.d_x,0,0,0,0,0],
        [0,self.d_y,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,self.d_z]])

        self.K_p = numpy.array([
        [self.p_x,0,0,0,0,0],
        [0,self.p_y,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,0],
        [0,0,0,0,0,self.p_z]])

        # Averaging parameters
        self.last_average = numpy.zeros(6)
        self.num_to_avg = 75 # At 50 hz this is 50 samples is one second of data
        self.outputs = deque([numpy.zeros(6) for i in range(0, self.num_to_avg)])
        
        self.desired_state_set = False
        self.desired_state = numpy.ones(6)
        self.desired_state_dot = numpy.ones(6)
        self.state = numpy.ones(6)
        self.previous_error = numpy.ones(6)
        self.state_dot = numpy.ones(6)
        self.state_dot_body = numpy.ones(6)

        self.lock = threading.Lock()

        # Get tf listener
        self.tf_listener = tf.TransformListener()

        rospy.Subscriber("pd_d_gain", Point, self.d_gain_callback)
        rospy.Subscriber("pd_p_gain", Point, self.p_gain_callback)
        rospy.Subscriber('/trajectory', PoseTwistStamped, self.desired_state_callback)
        rospy.Subscriber('/odom', Odometry, self.odom_callback)
        self.controller_wrench = rospy.Publisher('wrench', WrenchStamped, queue_size = 1)
        self.waypoint_progress = rospy.Publisher('waypoint_progress', Bool, queue_size = 1)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)

        self.z_error = 0
        self.x_error = 0
        self.y_error = 0

        self.dz_error = 0
        self.dx_error = 0
        self.dy_error = 0
Пример #15
0
class KillPlugin(Plugin):
    def __init__(self, context):
        super(KillPlugin, self).__init__(context)
        self.setObjectName('KillPlugin')

        self._listener = KillListener()
        self._broadcaster = KillBroadcaster(rospy.get_name(), 'Software kill using KillPlugin')
        self._kill_active = False

        self._widget = QWidget()
        loadUi(os.path.join(uipath, 'killplugin.ui'), self._widget)
        context.add_widget(self._widget)

        self._widget.findChild(QTableWidget, 'killTable').setHorizontalHeaderLabels(["Name", "Status", "Description"])

        self._widget.findChild(QPushButton, 'killButton').clicked.connect(self._on_kill_clicked)
        self._widget.findChild(QPushButton, 'unkillButton').clicked.connect(self._on_unkill_clicked)
        self._widget.findChild(QPushButton, 'runButton').clicked.connect(self._on_run_clicked)

        self._update_timer = QTimer(self._widget)
        self._update_timer.timeout.connect(self._on_update)
        self._update_timer.start(100)

    def _on_update(self):
        self._update_kills()
        self._update_kill()

    def _on_kill_clicked(self):
        self._kill_active = True
        self._broadcaster.send(True)
        self._update_kill()

    def _on_unkill_clicked(self):
        self._kill_active = False
        self._broadcaster.send(False)
        self._update_kill()

    def _on_run_clicked(self):
        self._on_unkill_clicked()

    def _update_kills(self):
        all_kills = self._listener.get_all_kills()
        if all_kills is not None:
            new_kills = {kill.id: kill for kill in self._listener.get_all_kills()}
        else:
            new_kills = {}

        table = self._widget.findChild(QTableWidget, 'killTable')

        row = 0
        while row < table.rowCount():
            id = table.item(row, 1)
            if id in new_kills:
                self._update_kill_entry(row, new_kills[id])
                del new_kills[id]
                row += 1
            else:
                table.removeRow(row)

        for kill in new_kills.values():
            row = table.rowCount()
            table.setRowCount(row+1)
            self._update_kill_entry(row, kill)

    def _update_kill_entry(self, row, kill):
        color = QColor(255, 255, 255) if not kill.active else QColor(255, 200, 200)
        self._update_item(row, 0, color, kill.id)
        self._update_item(row, 1, color, "Killed" if kill.active else "Unkilled")
        self._update_item(row, 2, color, kill.description)

    def _update_item(self, row, col, color, string):
        item = QTableWidgetItem(string)
        item.setBackground(color)
        self._widget.findChild(QTableWidget, 'killTable').setItem(row, col, item)

    def _update_kill(self):
        kills = self._listener.get_all_kills()
        if kills is not None:
            other_kill_count = len([kill for kill in kills
                                    if kill.id != rospy.get_name() and kill.active])
            self._widget.findChild(QPushButton, 'runButton').setVisible(other_kill_count == 0)
            self._widget.findChild(QPushButton, 'unkillButton').setVisible(other_kill_count > 0)

            status = 'Sub status: '
            if not self._listener.get_killed():
                status += '<span style="color:green">Running</span>'
            else:
                status += '<span style="color:red">Killed</span>'
            self._widget.findChild(QLabel, 'killStatusLabel').setText(status)
        else:
            self._widget.findChild(QPushButton, 'runButton').setVisible(False)
            self._widget.findChild(QPushButton, 'unkillButton').setVisible(False)
            self._widget.findChild(QLabel, 'killStatusLabel').setText('<span style="color:red">No kill information</span>')
Пример #16
0
    def __init__(self):

        # Old gains
        self.d_x = 175
        self.d_y = 90
        self.d_z = 60
        self.p_x = 30
        self.p_y = 30
        self.p_z = 40

        #self.d_x = 175
        #self.d_y = 90
        #self.d_z = 90
        #self.p_x = 40
        #self.p_y = 40
        #self.p_z = 100

        self.killed = False
        self.enable = True
        self.odom_active = False

        self.K_d = numpy.array([[self.d_x, 0, 0, 0, 0, 0],
                                [0, self.d_y, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, self.d_z]])

        self.K_p = numpy.array([[self.p_x, 0, 0, 0, 0, 0],
                                [0, self.p_y, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, self.p_z]])

        # Averaging parameters
        self.last_average = numpy.zeros(6)
        self.num_to_avg = 75  # At 50 hz this is 50 samples is one second of data
        self.outputs = deque(
            [numpy.zeros(6) for i in range(0, self.num_to_avg)])

        self.desired_state_set = False
        self.desired_state = numpy.ones(6)
        self.desired_state_dot = numpy.ones(6)
        self.state = numpy.ones(6)
        self.previous_error = numpy.ones(6)
        self.state_dot = numpy.ones(6)
        self.state_dot_body = numpy.ones(6)

        self.lock = threading.Lock()

        # Get tf listener
        self.tf_listener = tf.TransformListener()

        rospy.Subscriber("pd_d_gain", Point, self.d_gain_callback)
        rospy.Subscriber("pd_p_gain", Point, self.p_gain_callback)
        rospy.Subscriber('/trajectory', PoseTwistStamped,
                         self.desired_state_callback)
        rospy.Subscriber('/odom', Odometry, self.odom_callback)
        self.controller_wrench = rospy.Publisher('wrench',
                                                 WrenchStamped,
                                                 queue_size=1)
        self.waypoint_progress = rospy.Publisher('waypoint_progress',
                                                 Bool,
                                                 queue_size=1)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)

        self.z_error = 0
        self.x_error = 0
        self.y_error = 0

        self.dz_error = 0
        self.dx_error = 0
        self.dy_error = 0
Пример #17
0
    def __init__(self, name):
        # Desired pose
        self.desired_position = self.current_position = np.zeros(3)
        self.desired_orientation = self.current_orientation = np.zeros(3)
        #self.desired_twist = self.current_twist = Twist()

        # Goal tolerances before seting succeded
        self.linear_tolerance = rospy.get_param('linear_tolerance', 0.5)
        self.angular_tolerance = rospy.get_param('angular_tolerance',
                                                 np.pi / 10)
        self.orientation_radius = rospy.get_param('orientation_radius', 0.75)
        self.slow_down_radius = rospy.get_param('slow_down_radius', 5)

        # Speed parameters
        self.max_tracking_distance = rospy.get_param('max_tracking_distance',
                                                     5)
        self.min_tracking_distance = rospy.get_param('min_tracking_distance',
                                                     1)
        self.tracking_to_speed_conv = rospy.get_param('tracking_to_speed_conv',
                                                      1)
        self.tracking_slope = (
            self.max_tracking_distance - self.min_tracking_distance) / (
                self.slow_down_radius - self.orientation_radius)
        self.tracking_intercept = self.tracking_slope * self.orientation_radius + self.min_tracking_distance

        # Publishers
        self.traj_pub = rospy.Publisher('/trajectory',
                                        PoseTwistStamped,
                                        queue_size=10)

        # Set desired twist to 0
        #self.desired_twist.linear.x = self.desired_twist.linear.y = self.desired_twist.linear.z = 0
        #self.desired_twist.angular.x = self.desired_twist.angular.y = self.desired_twist.angular.z = 0

        # Initilize a line
        self.line = line(np.zeros(3), np.ones(3))

        # Wait for current position and set as desired position
        rospy.loginfo('Waiting for /odom')
        self.odom_sub = rospy.Subscriber('/odom',
                                         Odometry,
                                         self.odom_cb,
                                         queue_size=10)
        while not self.current_position.any(
        ):  # Will be 0 until an odom publishes (if its still 0 it will drift very very soon)
            pass

        # Initlize Trajectory generator with current position as goal
        # 	Set the line to be along our current orientation
        self.desired_position = self.current_position
        self.desired_orientation = self.current_orientation
        # 	Make a line along the orientation
        self.line = line(
            self.current_position,
            tools.normal_vector_from_rotvec(self.current_orientation) +
            self.current_position)
        self.redraw_line = False
        rospy.loginfo('Got current pose from /odom')

        # Kill handling
        self.killed = False
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)
        self.kill_broadcaster = KillBroadcaster(
            id=name, description='Tank steer trajectory_generator shutdown')
        try:
            self.kill_broadcaster.clear()  # In case previously killed
        except rospy.service.ServiceException, e:
            rospy.logwarn(str(e))
Пример #18
0
class Controller(object):
    def __init__(self):

        # Old gains
        self.d_x = 175
        self.d_y = 90
        self.d_z = 60
        self.p_x = 30
        self.p_y = 30
        self.p_z = 40

        #self.d_x = 175
        #self.d_y = 90
        #self.d_z = 90
        #self.p_x = 40
        #self.p_y = 40
        #self.p_z = 100

        self.killed = False
        self.enable = True
        self.odom_active = False

        self.K_d = numpy.array([[self.d_x, 0, 0, 0, 0, 0],
                                [0, self.d_y, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, self.d_z]])

        self.K_p = numpy.array([[self.p_x, 0, 0, 0, 0, 0],
                                [0, self.p_y, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, self.p_z]])

        # Averaging parameters
        self.last_average = numpy.zeros(6)
        self.num_to_avg = 75  # At 50 hz this is 50 samples is one second of data
        self.outputs = deque(
            [numpy.zeros(6) for i in range(0, self.num_to_avg)])

        self.desired_state_set = False
        self.desired_state = numpy.ones(6)
        self.desired_state_dot = numpy.ones(6)
        self.state = numpy.ones(6)
        self.previous_error = numpy.ones(6)
        self.state_dot = numpy.ones(6)
        self.state_dot_body = numpy.ones(6)

        self.lock = threading.Lock()

        # Get tf listener
        self.tf_listener = tf.TransformListener()

        rospy.Subscriber("pd_d_gain", Point, self.d_gain_callback)
        rospy.Subscriber("pd_p_gain", Point, self.p_gain_callback)
        rospy.Subscriber('/trajectory', PoseTwistStamped,
                         self.desired_state_callback)
        rospy.Subscriber('/odom', Odometry, self.odom_callback)
        self.controller_wrench = rospy.Publisher('wrench',
                                                 WrenchStamped,
                                                 queue_size=1)
        self.waypoint_progress = rospy.Publisher('waypoint_progress',
                                                 Bool,
                                                 queue_size=1)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)

        self.z_error = 0
        self.x_error = 0
        self.y_error = 0

        self.dz_error = 0
        self.dx_error = 0
        self.dy_error = 0

    def set_kill(self):
        self.killed = True
        rospy.logwarn('PD_Controller KILLED: %s' %
                      self.kill_listener.get_kills())

    def clear_kill(self):
        self.killed = False
        rospy.logwarn('PD_Controller ACTIVE: %s' %
                      self.kill_listener.get_kills())

    def d_gain_callback(self, msg):
        self.d_x = msg.x
        self.d_y = msg.y
        self.d_z = msg.z

        self.K_d = numpy.array([[self.d_x, 0, 0, 0, 0, 0],
                                [0, self.d_y, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, self.d_z]])

    def p_gain_callback(self, msg):
        self.p_x = msg.x
        self.p_y = msg.y
        self.p_z = msg.z

        self.K_p = numpy.array([[self.p_x, 0, 0, 0, 0, 0],
                                [0, self.p_y, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
                                [0, 0, 0, 0, 0, self.p_z]])

    def desired_state_callback(self, desired_posetwist):
        self.lock.acquire()
        self.desired_state_set = True

        self.desired_state = numpy.concatenate([
            xyz_array(desired_posetwist.posetwist.pose.position),
            transformations.euler_from_quaternion(
                xyzw_array(desired_posetwist.posetwist.pose.orientation))
        ])
        self.desired_state_dot = numpy.concatenate([
            xyz_array(desired_posetwist.posetwist.twist.linear),
            xyz_array(desired_posetwist.posetwist.twist.angular)
        ])
        self.lock.release()

    def odom_callback(self, current_posetwist):
        self.lock.acquire()
        self.odom_active = True

        # Grab position; 0 Z
        pose = xyz_array(current_posetwist.pose.pose.position)
        pose[2] = 0

        # Grab orientation; 0 pitch and roll
        orientation = numpy.array(
            transformations.euler_from_quaternion(
                xyzw_array(current_posetwist.pose.pose.orientation)))
        orientation[0:2] = 0

        self.state = numpy.concatenate([
            xyz_array(current_posetwist.pose.pose.position),
            transformations.euler_from_quaternion(
                xyzw_array(current_posetwist.pose.pose.orientation))
        ])
        self.state_dot = numpy.concatenate([
            xyz_array(current_posetwist.twist.twist.linear),
            xyz_array(current_posetwist.twist.twist.angular)
        ])
        if (not self.desired_state_set):
            self.desired_state = self.state
            self.desired_state_set = True
        self.lock.release()

    def main_loop(self, event):

        self.lock.acquire()

        #print 'desired state', desired_state
        #print 'current_state', state
        def smallest_coterminal_angle(x):
            return (x + math.pi) % (2 * math.pi) - math.pi

        # sub pd-controller sans rise
        rot = None
        # Get tf from /enu to /base_link
        #   Since we are dealing with differences and not absolute positions not translation is required
        try:
            (_,
             rot) = self.tf_listener.lookupTransform('/base_link', '/enu',
                                                     rospy.Time(0))
        except (tf.LookupException, tf.ConnectivityException,
                tf.ExtrapolationException) as e:
            rospy.logwarn('Tf exception: ' + str(e))

        if rot is not None:
            # Convert to euler angle ( we only care about rotation about z)
            theta = quat_to_rotvec(numpy.array(rot))[2]

            # Difference in /enu frame
            to_desired_state = self.desired_state[0:2] - self.state[0:2]

            # Convert to base_link
            s = numpy.sin(theta)
            c = numpy.cos(theta)
            rot_matrix_enu_base = numpy.array([[c, -s], [s, c]])
            to_desired_state = rot_matrix_enu_base.dot(to_desired_state)
            to_desired_state = numpy.insert(to_desired_state, 2,
                                            0)  # Append a zero for z

            #                                    Note: Angular differences are the same in base_link as enu so no tf required
            e = numpy.concatenate([
                to_desired_state,
                map(smallest_coterminal_angle,
                    self.desired_state[3:6] - self.state[3:6])
            ])  # e_1 in paper

            # Convert desired state dot into base_link
            #   angular velocities do not rquire transformation as they are differences (rendering them frameless)
            #   To convert velocites from enu + desired_orientation to base link:
            #       transform to enu: rotate the velocity vector by desired_orientation
            #       transform to base link: rotate the velocity vector by the angle between enu and base_link
            vels = self.desired_state_dot[0:2]
            theta2 = self.desired_state[5]
            s = numpy.sin(theta2)
            c = numpy.cos(theta2)
            rot_matrix_desired_enu = numpy.array([[c, -s], [s, c]])
            vels = rot_matrix_desired_enu.dot(vels)
            vels = rot_matrix_enu_base.dot(vels)

            vels = numpy.insert(vels, 2, 0)

            desired_state_dot = numpy.concatenate(
                [vels, self.desired_state_dot[3:6]])

            #print 'Desired_state tf: ', desired_state_dot
            e_dot = desired_state_dot - self.state_dot
            output = self.K_p.dot(e) + self.K_d.dot(e_dot)

            # Apply simple moving average filter
            new = output / self.num_to_avg
            old = (self.outputs[0] / self.num_to_avg)
            self.last_average = self.last_average - old + new
            self.outputs.popleft()
            self.outputs.append(output)

            # Resuse output var
            #print 'Outputs: ', self.outputs
            output = self.last_average

            #print 'Last Average: ', output
            self.lock.release()

            self.x_error = e[0]
            self.y_error = e[1]
            self.z_error = e[5]

            self.dx_error = e_dot[0]
            self.dy_error = e_dot[1]
            self.dz_error = e_dot[5]

            #self.to_terminal()

            if (not (self.odom_active)):
                output = [0, 0, 0, 0, 0, 0]
            if (self.enable & self.killed == False):
                self.controller_wrench.publish(
                    WrenchStamped(header=Header(
                        stamp=rospy.Time.now(),
                        frame_id="/base_link",
                    ),
                                  wrench=Wrench(
                                      force=Vector3(x=output[0],
                                                    y=output[1],
                                                    z=0),
                                      torque=Vector3(x=0, y=0, z=output[5]),
                                  )))

                if ((self.x_error < 1) & (self.y_error < 1) &
                    (self.z_error < 1)):
                    self.waypoint_progress.publish(True)

            if (self.killed == True):
                rospy.logwarn('PD_Controller KILLED: %s' %
                              self.kill_listener.get_kills())
                self.controller_wrench.publish(
                    WrenchStamped(header=Header(
                        stamp=rospy.Time.now(),
                        frame_id="/base_link",
                    ),
                                  wrench=Wrench(
                                      force=Vector3(x=0, y=0, z=0),
                                      torque=Vector3(x=0, y=0, z=0),
                                  )))

        else:
            self.lock.release()

    def timeout_callback(self, event):
        self.odom_active = False

    def to_terminal(self):
        print "X: ", self.x_error
        print "Y: ", self.y_error
        print "Z: ", self.z_error

        print "dX: ", self.dx_error
        print "dY: ", self.dy_error
        print "dZ: ", self.dz_error
Пример #19
0
    def __init__(self):

        '''

        Structure gain array for flexible use
        This allows the gain function to access all gains by simple indexing scheme
        Place x and y gains in the first row of the 6x3
        Place x gains in the bottom row
        the i_history array uses this scheme as well

        Gain array layout:

            [  p_x.   i_x.   d_x.]
            [  p_y.   i_y.   d_y.]
            [  0.      0.      0.]
            [  0.      0.      0.]
            [  0.      0.      0.]
            [  p_z.   i_z.   d_z.]

        '''

        self.K = numpy.zeros((6,3))
        self.K[0:6, 0:6] = [
            [p_x,  i_x, d_x], # pid_x
            [p_y, i_y, d_y], # pid_y
            [0,   0,  0],
            [0,   0,  0],
            [0,   0,  0],
            [p_z, i_z, d_z], # pid_z
        ]

        # Kill functions
        self.odom_active = False
        self.killed = False

        # Create arrays to be used
        self.desired_state = numpy.ones(6)
        self.desired_velocity = numpy.ones(6)
        self.current_state = numpy.zeros(6)
        self.current_velocity = numpy.zeros(6)
        self.current_error = numpy.ones(6)

        self.i_history = [[0 for x in range(1)] for x in range(6)] 
        self.i_history[0] = deque()
        self.i_history[1] = deque()
        self.i_history[5] = deque()
        self.integrator = numpy.zeros(6)
        self.Derivator= 0

        self.lock = threading.Lock()

        # Used to reset the desired state on startup
        self.desired_state_set = False

        # ROS components
        self.controller_wrench = rospy.Publisher('wrench', WrenchStamped, queue_size = 1)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)
        rospy.Subscriber('/trajectory', PoseTwistStamped, self.trajectory_callback)
        rospy.Subscriber('/odom', Odometry, self.odom_callback)
        rospy.Subscriber("pid_d_gain", Point, self.d_gain_callback)
        rospy.Subscriber("pid_p_gain", Point, self.p_gain_callback)
        rospy.Subscriber("pid_i_gain", Point, self.i_gain_callback)
Пример #20
0
class PID_controller:

    def __init__(self):

        '''

        Structure gain array for flexible use
        This allows the gain function to access all gains by simple indexing scheme
        Place x and y gains in the first row of the 6x3
        Place x gains in the bottom row
        the i_history array uses this scheme as well

        Gain array layout:

            [  p_x.   i_x.   d_x.]
            [  p_y.   i_y.   d_y.]
            [  0.      0.      0.]
            [  0.      0.      0.]
            [  0.      0.      0.]
            [  p_z.   i_z.   d_z.]

        '''

        self.K = numpy.zeros((6,3))
        self.K[0:6, 0:6] = [
            [p_x,  i_x, d_x], # pid_x
            [p_y, i_y, d_y], # pid_y
            [0,   0,  0],
            [0,   0,  0],
            [0,   0,  0],
            [p_z, i_z, d_z], # pid_z
        ]

        # Kill functions
        self.odom_active = False
        self.killed = False

        # Create arrays to be used
        self.desired_state = numpy.ones(6)
        self.desired_velocity = numpy.ones(6)
        self.current_state = numpy.zeros(6)
        self.current_velocity = numpy.zeros(6)
        self.current_error = numpy.ones(6)

        self.i_history = [[0 for x in range(1)] for x in range(6)] 
        self.i_history[0] = deque()
        self.i_history[1] = deque()
        self.i_history[5] = deque()
        self.integrator = numpy.zeros(6)
        self.Derivator= 0

        self.lock = threading.Lock()

        # Used to reset the desired state on startup
        self.desired_state_set = False

        # ROS components
        self.controller_wrench = rospy.Publisher('wrench', WrenchStamped, queue_size = 1)
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)
        rospy.Subscriber('/trajectory', PoseTwistStamped, self.trajectory_callback)
        rospy.Subscriber('/odom', Odometry, self.odom_callback)
        rospy.Subscriber("pid_d_gain", Point, self.d_gain_callback)
        rospy.Subscriber("pid_p_gain", Point, self.p_gain_callback)
        rospy.Subscriber("pid_i_gain", Point, self.i_gain_callback)

    def p_gain_callback(self, msg):
        x = msg.x
        y = msg.y
        z = msg.z

        self.K[0:2, 0] = [x,y]
        self.K[5, 0] = z

    def i_gain_callback(self, msg):
        x = msg.x
        y = msg.y
        z = msg.z

        self.K[0:2, 1] = [x,y]
        self.K[5, 1] = z

    def d_gain_callback(self, msg):
        x = msg.x
        y = msg.y
        z = msg.z

        self.K[0:2, 2] = [x,y]
        self.K[5, 2] = z

    def set_kill(self):
        self.killed = True
        rospy.logdebug('PD_Controller KILLED: %s' % self.kill_listener.get_kills())

    def clear_kill(self):
        self.killed = False
        rospy.logdebug('PD_Controller ACTIVE: %s' % self.kill_listener.get_kills())

    def trajectory_callback(self, desired_trajectory):
        self.lock.acquire()
        self.desired_state_set = True
        # Get desired pose and orientation 
        desired_pose = xyz_array(desired_trajectory.posetwist.pose.position)
        desired_orientation = transformations.euler_from_quaternion(xyzw_array(desired_trajectory.posetwist.pose.orientation))
        # Get desired linear and angular velocities
        desired_lin_vel = xyz_array(desired_trajectory.posetwist.twist.linear)
        desired_ang_vel = xyz_array(desired_trajectory.posetwist.twist.angular)
        # Add desired position to desired state i_historys
        self.desired_state = numpy.concatenate([desired_pose, desired_orientation])
        # Add desired velocities to velocity i_history
        self.desired_velocity = numpy.concatenate([desired_lin_vel, desired_ang_vel])
        self.lock.release()

    def odom_callback(self, current_pos):
        self.lock.acquire()
        self.odom_active = True
        # Grab current position and orientation and 0 linear Z and angluar X and Y
        # Get current position 
        current_position = xyz_array(current_pos.pose.pose.position)
        current_orientation = numpy.array(transformations.euler_from_quaternion(xyzw_array(current_pos.pose.pose.orientation)))
        # Zero unneccesary elements
        current_position[2] = 0
        current_orientation[0:2] = 0
        # Add current position to state i_history
        self.current_state = numpy.concatenate([current_position, current_orientation])
        # Get current velocities
        current_lin_vel = xyz_array(current_pos.twist.twist.linear)
        current_ang_vel = xyz_array(current_pos.twist.twist.angular)
        # Add current velocities to velocity i_history
        self.current_velocity = numpy.concatenate([current_lin_vel, current_ang_vel])
        # If the desired state has not yet been set, set desired and current as the same
        # Resets the controller to current position on bootup
        if (not self.desired_state_set):
            self.desired_state = self.current_state
            self.desired_state_set = True

        self.lock.release()

    def PID(self, variable):

        # Index in state number we want to access
        state_number = 0
        if variable == 'x': state_number = 0
        if variable == 'y': state_number = 1
        if variable == 'z': state_number = 5

        #self.current_error = self.desired_state[state_number] - self.current_state[state_number]
        #rospy.logdebug(variable + ": " + str(self.current_error[state_number]))
        p = self.K[state_number, 0] * self.current_error[state_number]
        i = (self.integrator[state_number] + self.current_error[state_number]) * self.K[state_number, 1]
        d = self.K[state_number, 2] * (self.current_error[state_number] - self.Derivator)

        # This section will be the FOPID implimentation, but I am still working on it
        if abs(self.current_error[state_number]) > 0: pass
            #i = i * (1 + abs(d))

        rospy.logdebug(self.current_error[state_number])
        rospy.logwarn('P' + variable + ": " + str(p))
        rospy.logwarn('I' + variable + ": " + str(i))
        rospy.logwarn('D' + variable + ": " + str(d))

        # Set temporary variable for use in integrator sliding window
        sliding_window = self.i_history[state_number]

        # append to integrator array
        sliding_window.append(i)

        # If array is larger than 5 items, remove item
        if len(sliding_window) > 5:
            sliding_window.pop()

        # Set up variables for next iteration
        # Sum only last 5 numbers of intergration
        self.Derivator = self.current_error[state_number]
        self.integrator[state_number] = sum(sliding_window)

        PID = p + i + d
        return PID

    def timeout_callback(self, event):
        self.odom_active = False

    def jacobian(self, x):
        # maps global linear velocity/euler rates -> body linear+angular velocities
        sphi, cphi = math.sin(x[3]), math.cos(x[3])
        stheta, ctheta = math.sin(x[4]), math.cos(x[4])
        spsi, cpsi = math.sin(x[5]), math.cos(x[5])
        
        J_inv = numpy.zeros((6, 6))
        J_inv[0:3, 0:3] = [
            [       ctheta * cpsi              ,        ctheta * spsi              ,        -stheta],
            [sphi * stheta * cpsi - cphi * spsi, sphi * stheta * spsi + cphi * cpsi,  sphi * ctheta],
            [cphi * stheta * cpsi + sphi * spsi, cphi * stheta * spsi - sphi * cpsi,  cphi * ctheta],]
        J_inv[3:6, 3:6] = [
            [1,     0,       -stheta],
            [0,  cphi, sphi * ctheta],
            [0, -sphi, cphi * ctheta],]
        return J_inv

    def main_loop(self, event):

        def smallest_coterminal_angle(x):
            return (x + math.pi) % (2*math.pi) - math.pi

        self.lock.acquire()

        # Get linear and angular error between desired and current pose - /enu
        linear_error = self.desired_state[0:3] - self.current_state[0:3]
        angular_error = map(smallest_coterminal_angle, self.desired_state[3:6] - self.current_state[3:6])

        # Combine errors into one array
        error_enu = numpy.concatenate([linear_error, angular_error])
        #rospy.logdebug(error_enu)
        # Translate /enu errors into /base_link errors
        error_base = self.jacobian(self.current_state).dot(error_enu)
        # Take away velocity from error to avoid overshoot
        final_error = error_base - self.current_velocity
        # Place errors to be sent into main error array
        self.current_error = [final_error[0], final_error[1], 0, 0, 0, final_error[5]]

        self.lock.release()

        # Send error values through PID controller
        x = self.PID('x')
        y = self.PID('y')
        z = self.PID('z')

        # Combine into final wrenches
        wrench = [x,y,0,0,0,z]

        # If odometry has not been aquired, set wrench to 0
        if (not(self.odom_active)):
            wrench = [0,0,0,0,0,0]

        # If ready to go...
        if (self.killed == False):
            self.controller_wrench.publish(WrenchStamped(
                header = Header(
                    stamp=rospy.Time.now(),
                    frame_id="/base_link",
                    ),
                wrench=Wrench(
                    force = Vector3(x= wrench[0],y= wrench[1],z= 0),
                    torque = Vector3(x=0,y= 0,z= wrench[5]),
                    ))
                    
                    )

        # If not ready to go...
        if (self.killed == True):
            rospy.logdebug('PD_Controller KILLED: %s' % self.kill_listener.get_kills())
            self.controller_wrench.publish(WrenchStamped(
                    header = Header(
                        stamp=rospy.Time.now(),
                        frame_id="/base_link",
                        ),
                    wrench=Wrench(
                        force = Vector3(x= 0,y= 0,z= 0),
                        torque = Vector3(x=0,y= 0,z= 0),
                        ))
                        
                        )
Пример #21
0
class PropaGatorGUI(Plugin):
    def __init__(self, contex):
        super(PropaGatorGUI, self).__init__(contex)

        # Initilize variables
        self._float_status = False
        self.last_odom_msg = Odometry()
        self._current_controller = 'Controller: Unknown'
        self._controller = ''
        self._controllers = []

        # Assign a name
        self.setObjectName('PropaGatorGUI')

        # Create a widget
        self._widget = QWidget()
        loadUi(os.path.join(cwd, 'propagatorgui.ui'), self._widget)
        self._widget.setObjectName('PropaGatorGUI')
        contex.add_widget(self._widget)

        # Grab all the children from the widget
        self._kill_label = self._widget.findChild(QLabel, 'kill_label')
        self._float_label = self._widget.findChild(QLabel, 'float_label')
        self._controller_label = self._widget.findChild(
            QLabel, 'controller_label')
        self._odom_x_label = self._widget.findChild(QLabel, 'odom_x_label')
        self._odom_y_label = self._widget.findChild(QLabel, 'odom_y_label')
        self._odom_yaw_label = self._widget.findChild(QLabel, 'odom_yaw_label')
        self._odom_d_x_label = self._widget.findChild(QLabel, 'odom_d_x_label')
        self._odom_d_y_label = self._widget.findChild(QLabel, 'odom_d_y_label')
        self._odom_d_yaw_label = self._widget.findChild(
            QLabel, 'odom_d_yaw_label')
        self._placeholder_label = self._widget.findChild(
            QLabel, 'placeholder_label')

        self._kill_push_btn = self._widget.findChild(QPushButton,
                                                     'kill_push_btn')
        self._float_push_btn = self._widget.findChild(QPushButton,
                                                      'float_push_btn')
        self._controller_combo_box = self._widget.findChild(
            QComboBox, 'controller_combo_box')

        # Load images
        self._green_indicator = QPixmap(
            os.path.join(cwd, 'green_indicator.png'))
        self._red_indicator = QPixmap(os.path.join(cwd, 'red_indicator.png'))
        self._placeholder_image = QPixmap(os.path.join(cwd, 'placeholder.png'))

        # Set up ROS interfaces
        self._kill_listener = KillListener()
        self._kill_broadcaster = KillBroadcaster(
            id='PropaGator GUI', description='PropaGator GUI kill')
        self._odom_sub = rospy.Subscriber('/odom', Odometry, self._odom_cb)
        self._float_sub = rospy.Subscriber('/controller/float_status', Bool,
                                           self._float_cb)
        self._float_proxy = rospy.ServiceProxy('/controller/float_mode',
                                               FloatMode)
        self._current_controller_sub = rospy.Subscriber(
            '/controller/current_controller', String,
            self._current_controller_cb)
        self._get_all_controllers_proxy = rospy.ServiceProxy(
            '/controller/get_all_controllers', get_all_controllers)
        self._request_controller_proxy = rospy.ServiceProxy(
            '/controller/request_controller', request_controller)

        # Connect push buttons
        self._kill_push_btn.toggled.connect(self._on_kill_push_btn_toggle)
        self._float_push_btn.toggled.connect(self._on_float_push_btn_toggle)

        # Connect combo boxes
        self._controller_combo_box.activated[str].connect(
            self._controller_combo_box_cb)

        # Set up update timer at 10Hz
        # A Qt timer is used instead of a ros timer since Qt components are updated
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self._onUpdate)
        self.update_timer.start(100)

        # Temp
        self._placeholder_label.setPixmap(self._placeholder_image)

    # Everything needs to be turned off here
    def shutdown_plugin(self):
        self.update_timer.stop()
        self._odom_sub.unregister()
        del self._odom_sub
        self._float_sub.unregister()
        del self._float_sub
        # Kill broadcaster is not cleared, the user should unkill before closing the GUI
        del self._kill_broadcaster
        del self._kill_listener

    # Subscriber callbacks
    # Since this is in a different thread it is possible and likely that
    #   the drawing thread will try and draw while the text is being changed
    #   this causes all kinds of mahem such as segmentation faults, double free, ...
    #   To prevent this from hapening this thread updates only none QT variables
    #   described here http://wiki.ros.org/rqt/Tutorials/Writing%20a%20Python%20Plugin
    def _odom_cb(self, msg):
        self.last_odom_msg = msg

    def _float_cb(self, status):
        self._float_status = status.data

    def _current_controller_cb(self, controller):
        self._controller = controller.data
        self._current_controller = 'Controller: ' + controller.data

    def _odom_update(self):
        pos = self.last_odom_msg.pose.pose.position
        yaw = quat_to_rotvec(
            xyzw_array(self.last_odom_msg.pose.pose.orientation))[2]
        vel = self.last_odom_msg.twist.twist.linear
        dYaw = self.last_odom_msg.twist.twist.angular.z

        self._odom_x_label.setText('X: %3.3f' % pos.x)
        self._odom_y_label.setText('Y: %3.3f' % pos.y)
        self._odom_yaw_label.setText('Yaw: %3.3f' % yaw)
        self._odom_d_x_label.setText('dX: %3.3f' % vel.x)
        self._odom_d_y_label.setText('dY: %3.3f' % vel.y)
        self._odom_d_yaw_label.setText('dYaw: %3.3f' % dYaw)

    # Push btn callbacks
    def _on_kill_push_btn_toggle(self, checked):
        if checked:
            self._kill_broadcaster.send(True)
        else:
            self._kill_broadcaster.send(False)

    def _on_float_push_btn_toggle(self, checked):
        # TODO: Check if float service active
        try:
            if checked:
                self._float_proxy(True)
            else:
                self._float_proxy(False)
        except rospy.service.ServiceException:
            pass

    # Combo box callbacks
    def _controller_combo_box_cb(self, text):
        self._request_controller_proxy(text)

    # Update functions
    def _updateStatus(self):
        # Check if killed
        if self._kill_listener.get_killed():
            self._kill_label.setPixmap(self._red_indicator)
        else:
            self._kill_label.setPixmap(self._green_indicator)

        # Check float status
        if self._float_status:
            self._float_label.setPixmap(self._red_indicator)
        else:
            self._float_label.setPixmap(self._green_indicator)

        # Check if in autonomous or RC
        self._controller_label.setText(self._current_controller)

    def _updateControl(self):
        # Wait until we get the first controller
        if self._controller == '':
            return

        controllers = self._get_all_controllers_proxy().controllers
        if controllers != self._controllers:
            self._controllers = controllers
            self._controller_combo_box.clear()
            self._controller_combo_box.addItems(controllers)

        index = self._controller_combo_box.findText(self._controller)
        if index != -1 and index != self._controller_combo_box.currentIndex():
            self._controller_combo_box.setCurrentIndex(index)

    def _updateLidar(self):
        pass

    def _onUpdate(self):
        self._updateStatus()
        self._updateControl()
        self._updateLidar()
        self._odom_update()
Пример #22
0
    def __init__(self, contex):
        super(PropaGatorGUI, self).__init__(contex)

        # Initilize variables
        self._float_status = False
        self.last_odom_msg = Odometry()
        self._current_controller = 'Controller: Unknown'
        self._controller = ''
        self._controllers = []

        # Assign a name
        self.setObjectName('PropaGatorGUI')

        # Create a widget
        self._widget = QWidget()
        loadUi(os.path.join(cwd, 'propagatorgui.ui'), self._widget)
        self._widget.setObjectName('PropaGatorGUI')
        contex.add_widget(self._widget)

        # Grab all the children from the widget
        self._kill_label = self._widget.findChild(QLabel, 'kill_label')
        self._float_label = self._widget.findChild(QLabel, 'float_label')
        self._controller_label = self._widget.findChild(
            QLabel, 'controller_label')
        self._odom_x_label = self._widget.findChild(QLabel, 'odom_x_label')
        self._odom_y_label = self._widget.findChild(QLabel, 'odom_y_label')
        self._odom_yaw_label = self._widget.findChild(QLabel, 'odom_yaw_label')
        self._odom_d_x_label = self._widget.findChild(QLabel, 'odom_d_x_label')
        self._odom_d_y_label = self._widget.findChild(QLabel, 'odom_d_y_label')
        self._odom_d_yaw_label = self._widget.findChild(
            QLabel, 'odom_d_yaw_label')
        self._placeholder_label = self._widget.findChild(
            QLabel, 'placeholder_label')

        self._kill_push_btn = self._widget.findChild(QPushButton,
                                                     'kill_push_btn')
        self._float_push_btn = self._widget.findChild(QPushButton,
                                                      'float_push_btn')
        self._controller_combo_box = self._widget.findChild(
            QComboBox, 'controller_combo_box')

        # Load images
        self._green_indicator = QPixmap(
            os.path.join(cwd, 'green_indicator.png'))
        self._red_indicator = QPixmap(os.path.join(cwd, 'red_indicator.png'))
        self._placeholder_image = QPixmap(os.path.join(cwd, 'placeholder.png'))

        # Set up ROS interfaces
        self._kill_listener = KillListener()
        self._kill_broadcaster = KillBroadcaster(
            id='PropaGator GUI', description='PropaGator GUI kill')
        self._odom_sub = rospy.Subscriber('/odom', Odometry, self._odom_cb)
        self._float_sub = rospy.Subscriber('/controller/float_status', Bool,
                                           self._float_cb)
        self._float_proxy = rospy.ServiceProxy('/controller/float_mode',
                                               FloatMode)
        self._current_controller_sub = rospy.Subscriber(
            '/controller/current_controller', String,
            self._current_controller_cb)
        self._get_all_controllers_proxy = rospy.ServiceProxy(
            '/controller/get_all_controllers', get_all_controllers)
        self._request_controller_proxy = rospy.ServiceProxy(
            '/controller/request_controller', request_controller)

        # Connect push buttons
        self._kill_push_btn.toggled.connect(self._on_kill_push_btn_toggle)
        self._float_push_btn.toggled.connect(self._on_float_push_btn_toggle)

        # Connect combo boxes
        self._controller_combo_box.activated[str].connect(
            self._controller_combo_box_cb)

        # Set up update timer at 10Hz
        # A Qt timer is used instead of a ros timer since Qt components are updated
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self._onUpdate)
        self.update_timer.start(100)

        # Temp
        self._placeholder_label.setPixmap(self._placeholder_image)
class KillPlugin(Plugin):
    def __init__(self, context):
        super(KillPlugin, self).__init__(context)
        self.setObjectName('KillPlugin')

        self._listener = KillListener()
        self._broadcaster = KillBroadcaster(rospy.get_name(),
                                            'Software kill using KillPlugin')
        self._kill_active = False

        self._widget = QWidget()
        loadUi(os.path.join(uipath, 'killplugin.ui'), self._widget)
        context.add_widget(self._widget)

        self._widget.findChild(QTableWidget,
                               'killTable').setHorizontalHeaderLabels(
                                   ["Name", "Status", "Description"])

        self._widget.findChild(QPushButton, 'killButton').clicked.connect(
            self._on_kill_clicked)
        self._widget.findChild(QPushButton, 'unkillButton').clicked.connect(
            self._on_unkill_clicked)
        self._widget.findChild(QPushButton, 'runButton').clicked.connect(
            self._on_run_clicked)

        self._update_timer = QTimer(self._widget)
        self._update_timer.timeout.connect(self._on_update)
        self._update_timer.start(100)

    def _on_update(self):
        self._update_kills()
        self._update_kill()

    def _on_kill_clicked(self):
        self._kill_active = True
        self._broadcaster.send(True)
        self._update_kill()

    def _on_unkill_clicked(self):
        self._kill_active = False
        self._broadcaster.send(False)
        self._update_kill()

    def _on_run_clicked(self):
        self._on_unkill_clicked()

    def _update_kills(self):
        all_kills = self._listener.get_all_kills()
        if all_kills is not None:
            new_kills = {
                kill.id: kill
                for kill in self._listener.get_all_kills()
            }
        else:
            new_kills = {}

        table = self._widget.findChild(QTableWidget, 'killTable')

        row = 0
        while row < table.rowCount():
            id = table.item(row, 1)
            if id in new_kills:
                self._update_kill_entry(row, new_kills[id])
                del new_kills[id]
                row += 1
            else:
                table.removeRow(row)

        for kill in new_kills.values():
            row = table.rowCount()
            table.setRowCount(row + 1)
            self._update_kill_entry(row, kill)

    def _update_kill_entry(self, row, kill):
        color = QColor(255, 255, 255) if not kill.active else QColor(
            255, 200, 200)
        self._update_item(row, 0, color, kill.id)
        self._update_item(row, 1, color,
                          "Killed" if kill.active else "Unkilled")
        self._update_item(row, 2, color, kill.description)

    def _update_item(self, row, col, color, string):
        item = QTableWidgetItem(string)
        item.setBackground(color)
        self._widget.findChild(QTableWidget,
                               'killTable').setItem(row, col, item)

    def _update_kill(self):
        kills = self._listener.get_all_kills()
        if kills is not None:
            other_kill_count = len([
                kill for kill in kills
                if kill.id != rospy.get_name() and kill.active
            ])
            self._widget.findChild(
                QPushButton, 'runButton').setVisible(other_kill_count == 0)
            self._widget.findChild(
                QPushButton, 'unkillButton').setVisible(other_kill_count > 0)

            status = 'Sub status: '
            if not self._listener.get_killed():
                status += '<span style="color:green">Running</span>'
            else:
                status += '<span style="color:red">Killed</span>'
            self._widget.findChild(QLabel, 'killStatusLabel').setText(status)
        else:
            self._widget.findChild(QPushButton, 'runButton').setVisible(False)
            self._widget.findChild(QPushButton,
                                   'unkillButton').setVisible(False)
            self._widget.findChild(QLabel, 'killStatusLabel').setText(
                '<span style="color:red">No kill information</span>')
Пример #24
0
    def __init__(self):
        # Initilize ros
        rospy.init_node('control_arbiter')

        # Vars
        self.controller = 'none'
        self.controllers = []
        self.floating = False
        self.killed = False
        self.continuous_angle_lock = threading.Lock()
        self.joint_lock = threading.Lock()
        self.full_lock = threading.Lock()
        self.wheel_lock = threading.Lock()
        self.thrust_lock = threading.Lock()

        # Services
        self.request_controller_srv = rospy.Service('request_controller',
                                                    request_controller,
                                                    self.request_controller_cb)
        self.register_controller_srv = rospy.Service(
            'register_controller', register_controller,
            self.register_controller_cb)
        self.float_srv = rospy.Service('float_mode', FloatMode,
                                       self.set_float_mode)
        self.get_all_controllers_srv = rospy.Service(
            'get_all_controllers', get_all_controllers,
            self.get_all_controllers_cb)

        # Publishers
        self.continuous_angle_pub = rospy.Publisher(
            '/dynamixel/dynamixel_continuous_angle_config',
            DynamixelContinuousAngleConfig,
            queue_size=10)
        self.full_pub = rospy.Publisher('/dynamixel/dynamixel_full_config',
                                        DynamixelFullConfig,
                                        queue_size=10)
        self.joint_pub = rospy.Publisher('/dynamixel/dynamixel_joint_config',
                                         DynamixelJointConfig,
                                         queue_size=10)
        self.wheel_pub = rospy.Publisher('/dynamixel/dynamixel_wheel_config',
                                         DynamixelWheelConfig,
                                         queue_size=10)
        self.port_pub = rospy.Publisher('/stm32f3discovery_imu_driver/pwm1',
                                        Float64,
                                        queue_size=10)
        self.starboard_pub = rospy.Publisher(
            '/stm32f3discovery_imu_driver/pwm2', Float64, queue_size=10)
        self.float_status_pub = rospy.Publisher('float_status',
                                                Bool,
                                                queue_size=1)
        self.current_controller_pub = rospy.Publisher('current_controller',
                                                      String,
                                                      queue_size=1)

        # Subscribers
        self.continuous_angle_sub = rospy.Subscriber(
            'dynamixel_continuous_angle_config',
            ControlDynamixelContinuousAngleConfig,
            self.continuous_angle_cb,
            queue_size=10)
        self.full_sub = rospy.Subscriber('dynamixel_full_config',
                                         ControlDynamixelFullConfig,
                                         self.full_cb,
                                         queue_size=10)
        self.joint_sub = rospy.Subscriber('dynamixel_joint_config',
                                          ControlDynamixelJointConfig,
                                          self.joint_cb,
                                          queue_size=10)
        self.wheel_sub = rospy.Subscriber('dynamixel_wheel_config',
                                          ControlDynamixelWheelConfig,
                                          self.wheel_cb,
                                          queue_size=10)
        self.thruster_sub = rospy.Subscriber('thruster_config',
                                             ControlThrustConfig,
                                             self.thruster_cb,
                                             queue_size=10)

        # Timers
        self.update_timer = rospy.Timer(rospy.Duration(0.1),
                                        self.status_update)

        # Kill
        self.kill_listener = KillListener(self.set_kill_cb, self.clear_kill_cb)
        self.kill_broadcaster = KillBroadcaster(
            id='control_arbiter', description='control_arbiter has shutdown')
        try:
            self.kill_broadcaster.clear()
        except rospy.service.ServiceException, e:
            rospy.logwarn(str(e))
Пример #25
0
	def __init__(self):
		# Initilization code
		self.killed = False
		self.kill_listener = KillListener(self.set_kill, self.clear_kill)