how to call rospy.init_node() twice - python

Im trying to call one node to do one action, and then continue to the next action. get the error: raise rospy.exceptions.ROSException("rospy.init_node() has already been called with different arguments: "+str(_init_node_args))
how can I stop the first node in order to continue to the next one?
I tried using rospy.signal_shutdown('Quit') but the hole program stopped, and not only the node that i wanted.
#!/usr/bin/env python
import os
import sys
import rospy
import baxter_interface
import time
import argparse
from geometry_msgs.msg import ( PoseStamped, Pose, Point, Quaternion,)
from std_msgs.msg import Header
from baxter_core_msgs.srv import ( SolvePositionIK, SolvePositionIKRequest,)
def ik_test(limb):
rospy.init_node("rsdk_ik_service_client", disable_signals=True)
ns = "ExternalTools/" + limb + "/PositionKinematicsNode/IKService"
iksvc = rospy.ServiceProxy(ns, SolvePositionIK)
ikreq = SolvePositionIKRequest()
hdr = Header(stamp=rospy.Time.now(), frame_id='base')
poses = {
'left': PoseStamped(
header=hdr,
pose=Pose(
position=Point(
x=0.657579481614,
y=0.851981417433,
z=0.0388352386502,
),
orientation=Quaternion(
x=-0.366894936773,
y=0.885980397775,
z=0.108155782462,
w=0.162162481772,
),
),
),
'right': PoseStamped(
header=hdr,
pose=Pose(
position=Point(
x=0.692002,
y=-0.360751,
z=-0.05133,
),
orientation=Quaternion(
x=-0.105882425658,
y=0.9364525476,
z=-0.0241838726041,
w=0.333557608721,
),
),
),
}
ikreq.pose_stamp.append(poses[limb])
try:
rospy.wait_for_service(ns, 5.0)
resp = iksvc(ikreq)
except (rospy.ServiceException, rospy.ROSException), e:
rospy.logerr("Service call failed: %s" % (e,))
return 1
if (resp.isValid[0]):
print("SUCCESS - Valid Joint Solution Found:")
# Format solution into Limb API-compatible dictionary
limb_joints = dict(zip(resp.joints[0].name, resp.joints[0].position))
print limb_joints
else:
print("INVALID POSE - No Valid Joint Solution Found.")
return limb_joints
def open_gripper():
rospy.init_node('Hello_Baxter')
limb = baxter_interface.Limb('right')
from baxter_interface import Gripper
right_gripper = Gripper('right')
joints_names= ['right_e0','right_e1','right_s0','right_s1','right_w0','right_w1','right_w2']
r=rospy.Rate(10) #10Hz
r.sleep()
baxter_interface.gripper.Gripper('right').open() #Open right gripper
return 0
def main():
arg_fmt = argparse.RawDescriptionHelpFormatter
parser = argparse.ArgumentParser(formatter_class=arg_fmt,
description=main.__doc__)
parser.add_argument(
'-l', '--limb', choices=['left', 'right'], required=True,
help="the limb to test"
)
args = parser.parse_args(rospy.myargv()[1:])
limb_joints=ik_test(args.limb)
limb = baxter_interface.Limb('right')
limb.move_to_joint_positions(limb_joints)
open_gripper()
return 0 #ik_test(args.limb)
if __name__ == '__main__':
sys.exit(main())
I expected the first node to shut down and the other to init, but i get the error above.

You seem to confusing the way that ROS nodes and python scripts are used. Your python script should be a single node. Within this node you can create and destroy different topics, services and actions at different times but you can only create one node once.
You should init a single at the start of your main function, then you can create the different services and actions that you need when you need them.
Hope this helps.

Related

get audio device GUID in Python

I am trying to get GUID of audio device. The GUID can be found in registry Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\ the guid should look like {0.0.0.00000000}.{37e73048-025a-47ea-bf9f-59d5ef8f2b43}
basically like this. but I want in python Getting GUID of audio output device (speaker,headphones)
I've tried myself but only thing I can find is to use command line and parse it in Python
import subprocess
sd = subprocess.run(
["pnputil", "/enum-devices", "/connected", "/class", "AudioEndpoint"],
capture_output=True,
text=True,
)
output = sd.stdout.split("\n")[1:-1]
def getDevices(devices):
deviceList = {}
for device in range(len(devices)):
if "Instance ID:" in devices[device]:
deviceList[devices[device+1].split(":")[-1].strip()] = devices[device].split("\\")[-1].strip()
return deviceList
print(getDevices(output))
which got me
{'Headset (Soundcore Life Q30 Hands-Free)': '{0.0.0.00000000}.{4ac89ef7-f00d-4069-b96b-421bd3276295}', 'Speakers (Echo Dot-BQP)': '{0.0.0.00000000}.{8085b216-297a-4d02-bc3d-83b997b79524}', 'Headphones (Soundcore Life Q30)': '{0.0.0.00000000}.{37e73048-025a-47ea-bf9f-59d5ef8f2b43}'}
Hopping there is better way
from __future__ import print_function
import comtypes
from pycaw.pycaw import AudioUtilities, IMMDeviceEnumerator, EDataFlow, DEVICE_STATE
from pycaw.constants import CLSID_MMDeviceEnumerator
def MyGetAudioDevices(direction="in", State = DEVICE_STATE.ACTIVE.value):
devices = []
# for all use EDataFlow.eAll.value
if direction == "in":
Flow = EDataFlow.eCapture.value # 1
else:
Flow = EDataFlow.eRender.value # 0
deviceEnumerator = comtypes.CoCreateInstance(
CLSID_MMDeviceEnumerator,
IMMDeviceEnumerator,
comtypes.CLSCTX_INPROC_SERVER)
if deviceEnumerator is None:
return devices
collection = deviceEnumerator.EnumAudioEndpoints(Flow, State)
if collection is None:
return devices
count = collection.GetCount()
for i in range(count):
dev = collection.Item(i)
if dev is not None:
if not ": None" in str(AudioUtilities.CreateDevice(dev)):
devices.append(AudioUtilities.CreateDevice(dev))
return devices
output_device = MyGetAudioDevices("out")
input_device = MyGetAudioDevices("in")
print(output_device)
print(input_device)
This worked for me

Why does desktop.getCurrentComponent() return None in PyUNO?

Trying to revive a PyUNO sample script called Wavelet to learn how LO works nowadays and get re-started. Since LibreOffice & UNO changed a bit from the script's creation time I am running into problems.
Managed to get the desktop object. Now I want to retrieve the open document's component. How do I achieve this properly? The desktop.getCurrentComponent() call returns None.
LibreOffice version: 6.4.6.2.
System: Ubuntu MATE 20.04 x86_64.
The code follows:
#!/usr/bin/python3
def TestWave(event):
wavelet = Wavelet(XSCRIPTCONTEXT)
wavelet.trigger( () )
import uno
import unohelper
import string
from com.sun.star.task import XJobExecutor
class Wavelet( unohelper.Base, XJobExecutor ):
def __init__( self, ctx ):
self.ctx = ctx
def trigger( self, args ):
desktop = self.ctx.ServiceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop", self.ctx )
doc = desktop.getCurrentComponent()
print('doc:', doc)
#try:
search = doc.createSearchDescriptor()
search.SearchRegularExpression = True
search.SearchString = "\\<(k|s|v|z|o|u|i|a) "
found = doc.findFirst( search )
while found:
print("found:", found.String)
found.String = string.replace( found.String, " ", u"\xa0" )
found = doc.findNext( found.End, search)
#except:
# pass
g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(
Wavelet,
"name.vojta.openoffice.Wavelet",
("com.sun.star.task.Job",),)
if __name__ == "__main__":
import os
# Start OpenOffice.org, listen for connections and open testing document
os.system( "loffice '--accept=socket,host=localhost,port=2002;urp;' --writer ./WaveletTest.odt &" )
# Get local context info
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext )
ctx = None
# Wait until the OO.o starts and connection is established
while ctx == None:
try:
ctx = resolver.resolve(
"uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
except:
pass
# Trigger our job
wavelet = Wavelet( ctx )
wavelet.trigger( () )
Output:
doc: None
Traceback (most recent call last):
File "./wavelet.py", line 62, in <module>
wavelet.trigger( () )
File "./wavelet.py", line 24, in trigger
search = doc.createSearchDescriptor()
AttributeError: 'NoneType' object has no attribute 'createSearchDescriptor'
Edit 1
Cross posted at the following address:
https://ask.libreoffice.org/en/question/283785/why-does-desktopgetcurrentcomponent-return-none-in-pyuno/
Try without giving desktop.getCurrentComponent() a variable, so erase doc =. I remember I had that problem, but did not understand why it was doing it. All I remember is that not naming it made my code work. That is the only advice I can give you.
Tried to wait until the document component becomes available. And it worked:
doc = None
while doc is None:
doc = desktop.getCurrentComponent()

Updating Appending List to a txt file

Hello currently i am studying python and i wanted to know on how you can have a list that is being appended if there is a change constantly to a txtfile. Wording is a hard here is the code anyways
list=[]
random_number=0
file_handler=open("history.txt","w")
file_handler.write(str(list))
lenght_cumulative_data=len(list)
confirmed.append(random_number)
Now what i want to accomplish is that the list variable of the number 0 would be shown in history.txt but that doesnt happen and lets just imagine that random_number is always changing I want the list variable to be able to always update itself. Like if let say random_number changes to 1 and then 2 I want list to be updated to [0,1,2]. How do you do that? I've been searching on youtube and all they gave me is this write function is there anyway someone could refrence it or have any ideas?
from os import stat
from _thread import start_new_thread
from time import sleep
List = []
class WatchFileForChanges:
def __init__(self, filename):
self.file = filename
self.cached_file = stat(self.file).st_mtime
def watch(self):
num = 0
while 1:
status = stat(self.file).st_mtime
if status != self.cached_file:
self.cached_file = status
#file changed
List.append(num)
num += 1
def main():
Watcher = WatchFileForChanges("file.txt")
start_new_thread(Watcher.watch, ())
while 1:
print(List)
sleep(1)
if __name__ == '__main__':
main()
This will do what you want.
If I understood you correctly, you want to append to the list every time a file changes.
Note: this answer will only work on Windows
changes.py:
# Adapted from http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html
import threading
import os
import win32file
import win32con
ACTIONS = {
1 : "Created",
2 : "Deleted",
3 : "Updated",
4 : "Renamed from something",
5 : "Renamed to something"
}
# Thanks to Claudio Grondi for the correct set of numbers
FILE_LIST_DIRECTORY = 0x0001
def monitor_changes(callback, path, filenames):
path = path or ""
if type(filenames) == "str":
filenames = (filenames,)
thread = threading.Thread(target=_monitor, args=(callback, path, filenames))
thread.start()
return thread
def _monitor(callback, path, filenames):
hDir = win32file.CreateFile (
path,
FILE_LIST_DIRECTORY,
win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
None,
win32con.OPEN_EXISTING,
win32con.FILE_FLAG_BACKUP_SEMANTICS,
None
)
while True:
#
# ReadDirectoryChangesW takes a previously-created
# handle to a directory, a buffer size for results,
# a flag to indicate whether to watch subtrees and
# a filter of what changes to notify.
#
# NB Tim Juchcinski reports that he needed to up
# the buffer size to be sure of picking up all
# events when a large number of files were
# deleted at once.
#
results = win32file.ReadDirectoryChangesW (
hDir,
1024,
True,
win32con.FILE_NOTIFY_CHANGE_LAST_WRITE,
None,
None
)
for action, file in results:
if filenames and file not in filenames and os.path.basename(file) not in filenames:
continue
callback(action, file)
if __name__ == '__main__':
# monitor by printing
t = monitor_changes(print, ".", None)
And in your main.py:
import changes
import os
my_list = []
def callback(action_id, filename):
# the function running means
# that the file has been modified
action_desc = changes.ACTIONS[action_id]
print(action_desc, filename)
with open(filename) as f:
my_list.append(f.read())
thread = changes.monitor_changes(callback, ".", "my_file_that_I_want_to_monitor.txt")
If you want to monitor all files in the directory, call monitor_changes with None as the third argument.
Note: this will monitor all subdirectories, so files with the same name but in different folders will trigger the callback. If you want to avoid this, then check the filename passed to your callback function is exactly what you want to monitor.

Is there a way to get the full path of the shell:appsfolder on Windows 10?

I'd like to be able to list the files in the shell:appsfolder in a python script but need the full path to do this using os.list. Is there a way to get the full path (or does anyone know it)? Alternatively, is there a different way I can list these files? Can I "cd" to it?
The idea behind the script is to automate the shortcut creation of all the Windows Store apps (identified by the fact they have a "long name" property I think) and extract those shortcuts to a folder where the program Launchy can detect them. I don't like having to manually go through the process of creating the shortcut (and renaming it to remove the " - shortcut) every time I download or remove an app so I thought I'd automate it.
Here's a function that hopefully does what you want in terms of creating shortcuts for the Windows Store apps that are listed in the "Applications" virtual folder (i.e. FOLDERID_AppsFolder). To classify Windows Store apps, it looks for an exclamation point in the Application User Model ID since the AUMID should be of the form "PackageFamily!ApplicationID" (see Automate Launching UWP Apps). For reliability it cross-checks each package family with the user's registered package families.
import os
import ctypes
import pywintypes
import pythoncom
import winerror
try:
import winreg
except ImportError:
# Python 2
import _winreg as winreg
bytes = lambda x: str(buffer(x))
from ctypes import wintypes
from win32com.shell import shell, shellcon
from win32com.propsys import propsys, pscon
# KNOWNFOLDERID
# https://msdn.microsoft.com/en-us/library/dd378457
# win32com defines most of these, except the ones added in Windows 8.
FOLDERID_AppsFolder = pywintypes.IID('{1e87508d-89c2-42f0-8a7e-645a0f50ca58}')
# win32com is missing SHGetKnownFolderIDList, so use ctypes.
_ole32 = ctypes.OleDLL('ole32')
_shell32 = ctypes.OleDLL('shell32')
_REFKNOWNFOLDERID = ctypes.c_char_p
_PPITEMIDLIST = ctypes.POINTER(ctypes.c_void_p)
_ole32.CoTaskMemFree.restype = None
_ole32.CoTaskMemFree.argtypes = (wintypes.LPVOID,)
_shell32.SHGetKnownFolderIDList.argtypes = (
_REFKNOWNFOLDERID, # rfid
wintypes.DWORD, # dwFlags
wintypes.HANDLE, # hToken
_PPITEMIDLIST) # ppidl
def get_known_folder_id_list(folder_id, htoken=None):
if isinstance(folder_id, pywintypes.IIDType):
folder_id = bytes(folder_id)
pidl = ctypes.c_void_p()
try:
_shell32.SHGetKnownFolderIDList(folder_id, 0, htoken,
ctypes.byref(pidl))
return shell.AddressAsPIDL(pidl.value)
except WindowsError as e:
if e.winerror & 0x80070000 == 0x80070000:
# It's a WinAPI error, so re-raise it, letting Python
# raise a specific exception such as FileNotFoundError.
raise ctypes.WinError(e.winerror & 0x0000FFFF)
raise
finally:
if pidl:
_ole32.CoTaskMemFree(pidl)
def enum_known_folder(folder_id, htoken=None):
id_list = get_known_folder_id_list(folder_id, htoken)
folder_shell_item = shell.SHCreateShellItem(None, None, id_list)
items_enum = folder_shell_item.BindToHandler(None,
shell.BHID_EnumItems, shell.IID_IEnumShellItems)
for item in items_enum:
yield item
def list_known_folder(folder_id, htoken=None):
result = []
for item in enum_known_folder(folder_id, htoken):
result.append(item.GetDisplayName(shellcon.SIGDN_NORMALDISPLAY))
result.sort(key=lambda x: x.upper())
return result
def create_shortcut(shell_item, shortcut_path):
id_list = shell.SHGetIDListFromObject(shell_item)
shortcut = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None,
pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink)
shortcut.SetIDList(id_list)
persist = shortcut.QueryInterface(pythoncom.IID_IPersistFile)
persist.Save(shortcut_path, 0)
def get_package_families():
families = set()
subkey = (r'Software\Classes\Local Settings\Software\Microsoft'
r'\Windows\CurrentVersion\AppModel\Repository\Families')
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, subkey) as hkey:
index = 0
while True:
try:
families.add(winreg.EnumKey(hkey, index))
except OSError as e:
if e.winerror != winerror.ERROR_NO_MORE_ITEMS:
raise
break
index += 1
return families
def update_app_shortcuts(target_dir):
package_families = get_package_families()
for item in enum_known_folder(FOLDERID_AppsFolder):
try:
property_store = item.BindToHandler(None,
shell.BHID_PropertyStore, propsys.IID_IPropertyStore)
app_user_model_id = property_store.GetValue(
pscon.PKEY_AppUserModel_ID).ToString()
except pywintypes.error:
continue
# AUID template: Packagefamily!ApplicationID
if '!' not in app_user_model_id:
continue
package_family, app_id = app_user_model_id.rsplit('!', 1)
if package_family not in package_families:
continue
name = item.GetDisplayName(shellcon.SIGDN_NORMALDISPLAY)
shortcut_path = os.path.join(target_dir, '%s.lnk' % name)
create_shortcut(item, shortcut_path)
print('{}: {}'.format(name, app_user_model_id))
example
if __name__ == '__main__':
desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0)
target_dir = os.path.join(desktop, 'Windows Store Apps')
if not os.path.exists(target_dir):
os.mkdir(target_dir)
update_app_shortcuts(target_dir)

win32pdh.EnumObjectItems call error

I'm running Python 2.7 in Windows 7, with pywin32-216-win32-py2.7 installed. I'm running the following code, and it runs fine on one computer but outputs an error on another (both Win7, Py2.7, same pywin library).
Error message:
File "C:\Energy\Support Sheets\Kill Excel.py", line 9, in GetProcessID
items, instances = win32pdh.EnumObjectItems( None, None, object, win32pdh.PERF_DETAIL_WIZARD )
error: (-1073738824, 'EnumObjectItems for buffer size', 'The specified object was not found on the computer.')
Full code:
import win32api, win32con
import win32pdh
import os
import signal
import time
def GetProcessID( name ) :
object = "Process"
items, instances = win32pdh.EnumObjectItems( None, None, object, win32pdh.PERF_DETAIL_WIZARD )
val = None
if name in instances :
hq = win32pdh.OpenQuery()
hcs = [ ]
item = "ID Process"
path = win32pdh.MakeCounterPath( ( None, object, name, None, 0, item ) )
hcs.append( win32pdh.AddCounter( hq, path ) )
win32pdh.CollectQueryData( hq )
time.sleep( 0.01 )
win32pdh.CollectQueryData( hq )
for hc in hcs:
type, val = win32pdh.GetFormattedCounterValue( hc, win32pdh.PDH_FMT_LONG )
win32pdh.RemoveCounter( hc )
win32pdh.CloseQuery( hq )
return val
def Kill_Process_pid(pid):
handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, 0, pid) #get process handle
win32api.TerminateProcess(handle, -1) #kill by handle
win32api.CloseHandle(handle) #close api
def Kill_Process(name):
pid = GetProcessID(name)
if pid:
try:
Kill_Process_pid(pid)
return True
except:
pass
else:
return False
# MAIN FUNCTION
print 'Killing Excel instances...',
while Kill_Process('EXCEL'):
time.sleep(0.2)
print 'Done!'
I had the same issue when the Process performance counter was disabled - apparently this can just happen. There are instructions here for how to re-enable the counters. If you can't install software on the machine, you can run regedit and search for keys called "Disable Performance Counters" and delete them.
After that, you may need to run "lodctr /R" on a cmd shell as Administrator to reload the performance counters before it will work.

Categories

Resources