大项目中期检查还有一个星期就要开始了,实验室里大家都在紧张的准备着。今天打开自己的博客,发现居然没有七月的achieve。
七月,一个美好的月份就这么凭空消失了,至少在这里找不到它的踪迹,这多少然人感到沮丧,于是我开始寻找七月的记忆,在八月八日把他们记录下来,顺便提醒自己不要再错过其他的月份。
1号的下午,坐火车从杭州回北京,那天天气很热,不知是不是杭州用温度极力驱散我们这群过客换得一时清静,反正我是一刻不想在这火炉子里锻炼了。第二天早晨到的北京,正如我车上所想的那样,北方的早晨要凉爽些,我深吸了一口清晨的灰尘奔赴寝室。接下来几天比较清闲,换了个寝室,从18栋换到了6栋,条件也比以前好多了,离着实验室也更近了。那段时原本想上来写篇日志,想大多数人一样抒发下旅途的感想,但苦于不知从何谈起也就搁浅了,后来就一直到今天,如果再然我谈浙江之行的感觉,我已全然谈不出了,仿佛已经融入我的意识,它就在那里。
看上去,七月的开始是清闲的,但这不意味着整个七月就像我一直认为的那样是假期的日子。在一次中期动员后终于进入状态了:每天的作息差不多是9:00到00:00,13号27号分别去了趟西安和上海出差。上海那次是当天去当天回,据说我们的车路过SB园,不过显然那个时候我觉得睡觉比SB更吸引我,毕竟SB天天有。这段时间虽然忙,但忙的很规律,项目在那次动员会过后也神奇的前进了不少,中期在即各种问题似乎也都要解决了。
在做项目时写了一个插件框架,是个个人项目,我叫它Yaps(Yet Another Plugin System),也算是为项目后期个架构做个实验,目前版本已经比较稳定了,之后考虑开源,放出来溜一溜。Yaps是Header File Only的轻量级插件框架,目前就Windows平台上的编译器Msvc6~10、Mingw而言,编译出来的插件是可以公用:创建导出类的对象,以及对象生命周期的维护,基本达到了独立于编译器的目标,下一步准备着移植到linux下,当然,我并没有打算做的如DnyObj那样做到插件的跨平台,只是想在linux下使用而已。
在忙里偷闲的时候把Effective Go看完了,觉得Go的风格正是自己期盼和喜欢的那种,是个神奇的语言,但愿能长久,不要像D那样一闪而过。我也有考虑,用Go写点东西,应该至少要比C++来的快些。此外,编译和尝试了许多library:GLFW、SDL、JsonCpp、PyhonQt、MyGUI、CEGUI、glv、Horde3D。特别值得一提的是Hord3D这个渲染引擎,很小巧,但却号称是下一代渲染引擎;更重要是他的philosophy只作一件事情,它的目标是作为其他项目的组件,你不必为使用Horde3D做其他额外的事情,拿来用就好,这也是我这么些年一直努力去做的事情,所以很有兴致的把它代码拿来读一读,如果拿读书来比喻,刚刚读完了它的序言,不过相比一些巨型项目来说还是读的完的,希望他能有更多引人入胜的情节。
好了,就写到者,去祭下五脏庙去。
Good day.
毕业了,前天和朋友们一起来杭州逛一逛,天宫不作美的是当天风雨大作,只好白天逛逛杭州的市中心。和武汉一样,商场里价格不菲的各种衣服,奢侈品,同学笑称:杭州的大洋和新世纪。
晚上雨不再那么大了,朦朦细雨中夜游西湖。刚被洗刷过的西湖,水面不是那么平静两岸相差1000年,古今文化在这里碰撞交融,雷峰塔夜里灯火流光格外刺眼,断桥上中仿佛出现古老的传说,让人有种想把感情都扔到西湖的冲动。
西湖纵然美,但过于公园化了,对摄影技术很菜的我来说,相机捕捉到得更多是人影。本来第二天想继续游览西湖其他人文景观,但听说还有可能下雨,所以就提前跑到西塘了。
我们住在河边的客栈,推开窗子古镇便引入眼帘,寰秀桥就在不远处看着客栈的观景台,坐在藤椅里吹着河。树、水、楼阁都摆好了pose随处取景便是幅画,和其他走马观花的游人一样,我们都是不是画面中的元素。到了夜里,西塘就想把自己藏起来了,卡片相机不中用了,只能用眼睛收藏这景色。泛舟在河上,安静的河面热闹的岸边,西塘好像在抱怨人们打扰了她千年的静谧。从河面上不停的闪光灯可以看出游人们都想留住眼前也色,但夜究竟是黑的,任凭你如何闪他依然在那里不为所动,一次一次打击着拍照的人们,可是人就是人,依然固执得闪着,夜的疏影就这样成了光的琉璃。
It’s a long time since my last updated. These days I was immersing in alcohol for celebrating our graduation. I was filled up with too many complex feelings to spilled out. The day after tomorrow I will receive my diploma and draw an end to my undergraduate life.
I write down this short post as a remark of the new beginning of my student life as well as a reminder of my best memories that elapsed.
饮酒歌
——昨日饮酒后,寝室小白同学兴起而做
幽幽月,声声乐,酒酣意浓心无却;
杯杯错,句句愁,苦短情长岁无愁。
乐以人间丝竹之天籁,难以言觥筹之清越;
晓以清风雨露之精华,亦非喻歧路之情殇。
征战沙场十余载,天意使然意相逢;
同窗四年苦与乐,天地造化神使然。
纵岁月之流逝,折戟之沉沙,沧海之桑田,世事之变幻;
然亘古之情义,越光阴之禁锢,展梦想之天翼,谱情义之永殇。
饮酒歌,饮酒歌,苦痛饮,乐无求;
歌吟酒,歌吟酒,醉舞月,人间游。
空意空,空满楼,人去楼空月泪流;
愁亦愁,几多愁,花自飘零水东流。
今天早起的火车到了武昌。
武昌这正朦朦下着小雨,不热也不清爽,有点闷,像极了当时的心情。
这次回来主要是为大学生涯画上个句号,离别总是愁的,亲爱的同学们,生活一起四年了,下个月一过大家都各奔东西,不知何时才能相聚,所以让我们珍惜这“最后”的日子吧。
不过,在享受大学最后时光的日子前,还要把毕业论文这个遭天杀的事情弄完,一回宿舍谈论的便是这令人抓狂的事情。我相信苦尽甘来,论文呢这点点“小苦”过后一定是兄弟们开心的畅饮“来来来,干了这杯还有第二杯”……
今天毕设代码暂时算告一段落了,在上次中期的基础上加入了Phantom desktop的接入,提供触力觉反馈。其中触力觉反馈使用的是OpenHaptic的HDAPI
为了提供Haptic的支持主要解决2个问题
- Phantom设备的ServoLoop 1khz的力渲染与VTK15~30帧的图形渲染
- Phantom设备坐标系与VTK世界坐标系的匹配
关于问题1有两种解决的方法:
- 由于VTK的对象实现了subject/observer的模式,所以可以添加一个observer
- 使用Timer每间隔一段时间同步设备状态,渲染图形
由于UI是用QT实现的,所以VTK并不能自己处理重绘事件,所以这里选择了第2种方法,设置timer。在此之前曾尝试使用单独的绘制线程,但是由于VTK和OpenHaptic单独管理各自线程并且机制不同,无法在合适的时间同步设备状态,所以便用timer,这样使得图形渲染在同意线程中执行,也符合逻辑。
关于问题2
通过HDAPI可以获得探针姿态变换矩阵,利用HDU里的
void hduMapWorkspaceModel(const HDdouble *modelMatrix,
const HDdouble *projMatrix,
HDdouble *wsModelMatrix);
可以获得设备坐标系到世界坐标的变换,唯一要注意的是VTK内部矩阵是左乘,而OpenHaptic和OpenGL一样是右乘。
下面的代码片段描述了获得变换矩阵的方法
// get current render window vtkRenderer *ren = this->renderer_ ; // calculate the aspect from render window double aspect[2]; ren->ComputeAspect(); ren->GetAspect(aspect); double aspect2[2]; ren->vtkViewport::ComputeAspect(); ren->vtkViewport::GetAspect(aspect2); double aspectModification = aspect[0]*aspect2[1]/(aspect[1]*aspect2[0]); // get view port int viewport[4] ; ren->GetTiledSizeAndOrigin( // width viewport + 2, // height viewport + 3, // lower left x viewport, // lower left y viewport+1 ) ; // get the projection matrix vtkSmartPointer projection = vtkSmartPointer::New(); projection->DeepCopy(this->renderer_->GetActiveCamera() ->GetProjectionTransformMatrix( aspectModification*(viewport[2]/viewport[3]), -1.0, 1.0)) ; projection->Transpose() ; // get model view matrix vtkSmartPointer modelview = vtkSmartPointer::New(); modelview->DeepCopy(this->renderer_->GetActiveCamera() ->GetViewTransformMatrix()) ; modelview->Transpose() ; // Compute the transform for going from device coordinates to world // coordinates based on the current viewing transforms. ::hduMapWorkspaceModel(modelview->Element[0], projection->Element[0], this->workspace_model_) ;
下面的片段描述了如何利用获得的矩阵调整绘制视图中指针的姿态和位置。需要注意的是,变换之后会包换缩放的信息,如果不希望指针被莫名奇妙的缩放的话,需要去除缩放分量,可以使用vtkTransform类完成。
IHapticDevice::IHapticDeviceState *state =
this->device_in_graphic_->getCurrentState() ;
vtkSmartPointer workspace_model = vtkSmartPointer::New() ;
workspace_model->DeepCopy(state->getParentCumulativeTransform()) ;
workspace_model->Transpose() ;
vtkSmartPointer device_transform = vtkSmartPointer::New() ;
device_transform->DeepCopy(state->getTransform()) ;
device_transform->Transpose() ;
vtkSmartPointer device2view = vtkSmartPointer::New() ;
// set to the post multiply
device2view->PostMultiply() ;
// transform in work space
device2view->Concatenate(device_transform) ;
// transform to VTK view
device2view->Concatenate(workspace_model) ;
// set user transform
this->cursor_->SetPosition(device2view->GetPosition()) ;
this->cursor_->SetOrientation(device2view->GetOrientation()) ;
(完)
做了一个多月的毕业设计,今天实验室例会上给老师做了个报告,同时悲痛的得知这个难得的暑假估计大半时间要贡献给实验室了
今天报告的PPT
视频演示 : 清晰版 (On youtube)
在C++中一个类的友元函数或者友元类可以实现访问该类私有变量或者方法。但是对于静态方法使用声明友元类的方法却不能如愿,例如:
class Bar ;
class Foo {
public :
// do some custom initialize
static Bar *GetBar() { return new Bar() ;}
};
class Bar {
private:
Bar(){ }
// friend class Foo ; will cause the compile error
friend Bar *Foo::GetBar() ;
} ;
从上面的例子可以进一步理解类的静态成员的含义:属于类的上下文中,而不绑定于特定的对象(即无隐含的this指针)。
看着旁边的倒计时条,马上10.04就要发布了,虽然早就开始用beta的但是正式版的到来还是让人感到有点小兴奋,这几天ubuntu的升级也更加频繁了。
中午读googlereader时候看到皓哥写了篇博客,突然觉得心里空了一下。
以前大家都在一起有说有笑,转眼就各奔东西了,而且生活仿佛回到了高中的时候,简单到单调,每天两点一线之间不知道为了什么奔波。还记得以前每天的饭量相当于现在一的顿饭(老妈知道了肯定高兴),其实不是能吃了,是真的饿了……
还记得高中时物理老师总告诉我们生活是美好的,有点抽象了,我觉得向照镜子,当你微笑时生活也在对你微笑。
不要问我永远有多远,我真的不忍心告诉你:不到三年了。
现在要做的就是饱满激情,想着理想前进前进前前进。