[SOLVED]'NoneType' object has no attribute 'attachPattern'

Hi, i’m trying to install panda3d with artoolkit support. in ubuntu 12.10 and 11.10 all the libraries running, but in 12.10 after build successful the source, panda not found artoolkit.
In 11.10 i compile all the libraries and install oneiric package, but when i run a example of artoolkit i obtain this error:

    self.ar.attachPattern("ar/patt.sample1", self.ralphFlag)
AttributeError: 'NoneType' object has no attribute 'attachPattern'

I run five examples (downloaded, not edited ) with the same error (the second line). Maybe is simple, i have no experience with panda.

Thanks for advance.

Welcome to the forums!

Can you show more of your code?

Thanks!

Another example (more short), same error:

import direct.directbase.DirectStart
from pandac.PandaModules import ARToolKit,WebcamVideo,Texture,CardMaker,Vec2,Point2
from direct.task import Task

class EjemploRealidadAumentada:
    	"""
	ejemplo de realidad aumentada
	
	Requerimientos:
	
	- Panda3D (ult. version probada: 1.6.2)
	- ARToolkit. (version probada: 2.72.1)
	"""

	def __init__(self):
		"""
		Inicia la webcam, importa el modelo y lo vincula al patron
		AR a buscar.
		"""
		# Inicia la webcam
		option = WebcamVideo.getOption(0)  
		self.cursor = option.open() 
		
		# Genera una textura que contiene el "feed" de la webcam
		self.tex = Texture('movie') 
		self.tex.setTexturesPower2(0) 
		self.cursor.setupTexture(self.tex)
		videoTextureScale = Vec2(option.getSizeX()/float(self.tex.getXSize()), option.getSizeY()/float(self.tex.getYSize())) 		
	
		# Crea una card que muestra la imagen capturada por la webcam
		cm = CardMaker("background-card") 
		cm.setFrame(-videoTextureScale[1],videoTextureScale[1],-videoTextureScale[0],videoTextureScale[0]) 
		# Pone las coordenadas uv de la card, y-scale debe estar reversado.
		cm.setUvRange(Point2(videoTextureScale[0],0), Point2(0,videoTextureScale[1])) 
		card = render2d.attachNewNode(cm.generate()) 
		card.setTexture(self.tex)

		#Configura el orden de renderizacion manualmente para renderizar la card detras de la escena. 
		base.cam.node().getDisplayRegion(0).setSort(20) 
		
		#Carga el modelo del panda (incluido con Panda3D)
		b = loader.loadModel("models/ralph")
		
		b.setScale(0.1)
		
		#Inicia ARToolkit, y vincula el patron dado en el archivo .hiro al modelo cargado.
		self.ar = ARToolKit.make(base.cam, "ar/camera_para.dat", 1) 
		b.reparentTo(self.ar)
		self.ar.attachPattern("ar/patt.sample1", b) 
		
		# Agrega el task ARTask el cual se encarga de actualizar la AR.
		taskMgr.add(self.actualizarAR, "ARTask")


	def actualizarAR(self,task): 
		"""
		Revisa la escena y actualiza el AR.
		"""
		if self.cursor.ready():
			self.cursor.fetchIntoTexture(0, self.tex, 0) 
			self.ar.analyze(self.tex, True) 
		return Task.cont
		
		
		
ejemplo = EjemploRealidadAumentada()
run()
DirectStart: Starting the game.
Known pipe types:
  glxGraphicsPipe
(all display modules loaded.)
:display:glxdisplay(warning): No suitable FBConfig contexts available; using XVisual only.
depth_bits=24 color_bits=24 alpha_bits=8 stencil_bits=8 back_buffers=1 force_hardware=1 
:vision(error): Cannot load ARToolKit camera config
Traceback (most recent call last):
  File "/home/timbis/arsample/sample.py", line 66, in <module>
    ejemplo = EjemploRealidadAumentada()
  File "/home/timbis/arsample/sample.py", line 48, in __init__
    b.reparentTo(self.ar)
TypeError: NodePath.reparent_to() argument 1 must be NodePath, not NoneType

Well, the problem is really in your code. “b.reparentTo(self.ar)” is simply wrong, because self.ar is not a NodePath, so you can’t reparent b to it.

if i comment this line i obtain the same error than others examples:

DirectStart: Starting the game.
Known pipe types:
  glxGraphicsPipe
(all display modules loaded.)
:display:glxdisplay(warning): No suitable FBConfig contexts available; using XVisual only.
depth_bits=24 color_bits=24 alpha_bits=8 stencil_bits=8 back_buffers=1 force_hardware=1 
:vision(error): Cannot load ARToolKit camera config
Traceback (most recent call last):
  File "/home/timbis/arsample/sample.py", line 66, in <module>
    ejemplo = EjemploRealidadAumentada()
  File "/home/timbis/arsample/sample.py", line 49, in __init__
    self.ar.attachPattern("ar/patt.sample1", b) 
AttributeError: 'NoneType' object has no attribute 'attachPattern'

Ah, you failed to include the actual error in your original post:

:vision(error): Cannot load ARToolKit camera config 

This means that it failed to load your camera config file. Does the file ar/camera_para.dat actually exist, and is the path specified relative to the current working directory?

Aff, only works with absolute path. After fix this works, thanks.

I solved the problem using this code for relative path:

Path=os.path.abspath(sys.path[0])
RelativePath=Filename.fromOsSpecific(Path).getFullpath()

Thanks!

It’s not recommended to use sys.path[0] since it’s not very reliable.
However, relative paths work fine for me in ARToolKit.make. Are you sure you’re running Python in the directory that your paths are relative to?

To get the full path of the directory where your code is in non-os-specific form, use this:

import os
from panda3d.core import Filename
print Filename.fromOsSpecific(Filename(os.path.abspath(__file__)).getDirname())

It uses the magic name file which is the name of the python file that name is mentioned in.

Well, the location of the main Python file is also in base.mainDir. So, if you insist on using absolute paths, you might as well use this:

self.ar.attachPattern(Filename(base.mainDir, "ar/patt.sample1"), b)

i have same problem but your solution don’t work

from direct.showbase.ShowBase import ShowBase
from direct.task.TaskManagerGlobal import taskMgr
from panda3d.core import *
from panda3d.vision import WebcamVideo, ARToolKit

loadPrcFileData("", "textures-power-2 none")  # the webcam feed can not be made into a power of two texture
loadPrcFileData("","auto-flip 0")  # usualy the drawn texture lags a bit behind the calculted positions. this is a try to reduce the lag.

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        # self.disableMouse()
        self.physics = False
        option = WebcamVideo.getOption(0)
        self.tex = MovieTexture(option)
        # self.tex.setKeepRamImage(True)
        cm = CardMaker("card")
        cm.setUvRange(Point2(0, 0), Point2(1, 1))
        cm.setFrame(-1, 1, -1, 1)
        card = self.render2d.attachNewNode(cm.generate())
        card.setTexture(self.tex)


        # Starting ARToolkit
        self.cam.node().getDisplayRegion(0).setSort(20)
        self.ar = ARToolKit.make(self.cam, './camera_para.dat', 1)


        # Setting up the GUI
        # self.buttonLeftObject = DirectButton(text="Previous", pos=Vec3(-0.53, 0, -0.75), scale=.05,
        #                                      command=self.changeObject, extraArgs=["left"])
        # self.buttonRightObject = DirectButton(text="Next", pos=Vec3(-0.35, 0, -0.75), scale=.05,
        #                                       command=self.changeObject, extraArgs=["right"])
        self.prep = False
        self.changeObject()
        taskMgr.add(self.updatePatterns, 'updatePatterns')

    #Filename.fromOsSpecific(Filename(os.path.abspath(__file__)).getDirname())
    # Changing selected object on secondary pattern
    def changeObject(self):
        pandaActor = self.loader.loadModel("teapot.egg")
        pandaActor.reparent_to(self.render)
        self.ar.attachPattern(Filename(self.mainDir,'/ar/patt.sample1'), pandaActor)


    def updatePatterns(self, task):
        self.ar.analyze(self.tex)
        return task.cont

app = MyApp()
app.run()

You’re not using the right path. You’re using /ar/patt.sample1 which will look from the root of the filesystem.